1. 程式人生 > >精通Spring+4.x++企業開發與實踐之IoC容器中裝配Bean

精通Spring+4.x++企業開發與實踐之IoC容器中裝配Bean

Spring配置概述

Spring屬性注入

JavaBean關於屬性命名的特殊規範

Spring配置檔案中的<property></property>元素所指定的屬性名和Bean實現類的Setter方法滿足Sun JavaBean的屬性命名規範:xxx的屬性對應的setXxx()方法。 注意:需要滿足:"變數的前兩個字母要全大寫,要麼全小寫"。否則會出現具有誤導性的錯誤。

建構函式注入

1.需要提供一個有參建構函式,可以按型別匹配注入,按所以匹配注入,聯合型別和所以匹配注入,通過自身型別反射匹配注入 2.建構函式注入的問題,可能出現迴圈依賴的問題,導致程式無法啟動,只要改成屬性注入即可解決這個問題。 例子: ConstructorInject.java

public class ConstructorInject {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:iocdemo.xml");
		Person person = (Person) ctx.getBean("p2");
		System.out.println(person.toString());
	}
}

iocdemo.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="person" class="com.flexible.beans.Person">
	<property name="userName"><value>zhangsan</value></property>
	<property name="userAge"><value>20</value></property>
</bean>

	<bean id="p2" class="com.flexible.beans.Person">
		<constructor-arg type="java.lang.String"><value>zhangsan</value></constructor-arg>
		<constructor-arg type="java.lang.Integer"><value>28</value></constructor-arg>
	</bean>
</beans>

Person.java

public class Person {
public String userName;
public Integer userAge;

	public Person() {
	}

	public Person(String userName, Integer userAge) {
		this.userName = userName;
		this.userAge = userAge;
	}

	public String getUserName() {
		return userName;
	}

	public void setUserName(String userName) {
		this.userName = userName;
	}

	public Integer getUserAge() {
		return userAge;
	}

	public void setUserAge(Integer userAge) {
		this.userAge = userAge;
	}

	[@Override](https://my.oschina.net/u/1162528)
	public String toString() {
		return "Person{" +
				"userName='" + userName + '\'' +
				", userAge=" + userAge +
				'}';
	}
}

工廠方法注入

1.非靜態的工廠
xml配置如下:
		<bean id="factory" class="com.flexible.factorymethod.NonStaticFactoryMethod"></bean>
	<bean id="p3" factory-bean="factory" factory-method="createPerson"></bean>
2.工廠程式碼如下:
/**
 * 使用非靜態的工廠
 */
public class NonStaticFactoryMethod {
	/**
	 * 工廠的建立方法
	 * [@return](https://my.oschina.net/u/556800)
	 */
	public Person createPerson(){
	Person p = new Person();
	p.setUserName("lisi");
	p.setUserAge(20);
	return p;
}
}

測試方法如下:

		//非靜態的方式
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:iocdemo.xml");
		Person person = (Person) ctx.getBean("p3");
		System.out.println(person.toString());

靜態方法: xml配置如下: <bean id="p4" class="com.flexible.factorymethod.StaticMethod" factory-method="createPerson"></bean> 工廠類如下: public class StaticMethod {

	/**
	 * 工廠的建立方法
	 *
	 * [@return](https://my.oschina.net/u/556800)
	 */
	public static Person createPerson() {
		Person p = new Person();
		p.setUserName("lisi");
		p.setUserAge(20);
		return p;
	}
}

測試方法: //靜態的方式 Person person2 = (Person) ctx.getBean("p3"); System.out.println(person2.toString());

注入引數

Spring不但可以將String,int等字面值注入Bean中,還可以將集合,Map等型別的資料注入Bean中,還可以注入配置檔案的其他Bean。

字面值

字面值標識可以使用字串表示的值,這些值可以通過<value></value>元素注入。xml中包含5個特殊字元,分別是&,<,>,`,'。如果包含這些這些特殊字元,就需要使用<![CDATA[]]特殊標籤。

注意: 一般情況下,XML解析器會忽略元素標籤內部字串的前後空格,但是Spring卻不會忽略元素標籤內部字串的字串的前後空格,如果通過以下配置為屬性注入值<property name="xx"><value> xxx xx</value></property>,那麼前後,中間的空格將會被一起賦值給xx屬性。

引入其他的Bean

xml檔案如下:

	<bean id="p5" class="com.flexible.beans.Person">
		<property name="userName" value="wangwu"></property>
		<property name="userAge" value="20"></property>
	</bean>
	<bean id="h1" class="com.flexible.beans.House">
		<property name="length" value="100"></property>
		<property name="width" value="80"></property>
		<property name="height" value="60"></property>
		<property name="person"><ref bean="p5"></ref></property>
	</bean>

<ref></ref>元素可以通過以下3個屬性引用容器中的其他Bean。 1.bean:通過該屬性可以引用同一容器或者父容器中的Bean,這是最常見的形式 2.local:通過該屬性只能引用同一配置檔案中定義的Bean,他可以利用XML解析器自動檢驗引用的合法性,以便開發者再編寫配置時能夠幾時發現並糾正配置的錯誤。 3.parent:引用父容器中的Bean,如<ref parent="car">的配置說明car的Bean是父容器中的Bean.

Bean類 public class House {

	private Double length;

	private Double width;

	private Double height;

	private Person person;
	public House() {
	}

	public Double getLength() {
		return length;
	}

	public void setLength(Double length) {
		this.length = length;
	}

	public Double getWidth() {
		return width;
	}

	public void setWidth(Double width) {
		this.width = width;
	}

	public Double getHeight() {
		return height;
	}

	public void setHeight(Double height) {
		this.height = height;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	[@Override](https://my.oschina.net/u/1162528)
	public String toString() {
		return "House{" +
				"length=" + length +
				", width=" + width +
				", height=" + height +
				", person=" + person +
				'}';
	}
}

測試例子:

public class BeanInjectDemo {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:iocdemo.xml");
		House house = (House) ctx.getBean("h1");
		System.out.println(house.toString());
	}
}

內部Bean

內部Bean和Java的匿名內部類相似,既沒有名字,也不能被其他的Bean引用,只能在宣告處為外部Bean提供例項注入。 內部Bean幾時提供了id,name,scope屬性,也會被忽略。scope預設prototype型別。

	<bean id="h1" class="com.flexible.beans.House">
		<property name="length" value="100"></property>
		<property name="width" value="80"></property>
		<property name="height" value="60"></property>
		<property name="person">
		<bean id="p5" class="com.flexible.beans.Person">
		<property name="userName" value="wangwu"></property>
		<property name="userAge" value="20"></property>
		</bean>
	</property>
	</bean>

null值

如果希望給Bean的某個屬性賦值一個null,如果使用<property name="xx"><value></value></property>這樣是達不到預期的效果的,但是可以使用<property name="xx"><null/></property>

級聯屬性

javaBean程式碼

public class Car {

	Person person = new Person();

	public Car() {
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

	[@Override](https://my.oschina.net/u/1162528)
	public String toString() {
		return "Car{" +
				"person=" + person +
				'}';
	}
}

xml配置如下:

	<bean id="car" class="com.flexible.beans.Car">
		<property name="person.userName" value="zhaoliu"></property>
		<property name="person.userAge" value="20"></property>
	</bean>

測試程式碼:

public class CascadeDemo {

	public static void main(String[] args) {

		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:iocdemo.xml");
		Car car = (Car) ctx.getBean("car");
		System.out.println(car.toString());
	}
}

集合屬性注入

Favorite.java

public class Favorite {
	/**
	 * List集合
	 */
	private List<String> favoties = new ArrayList<>();
	/**
	 * map集合
	 */
	private Map<String,String> map = new HashMap<>();

	/**
	 *property,看作是特殊的map
	 */
	private Properties properties = new Properties();
	public Favorite() {
	}

	public List<String> getFavoties() {
		return favoties;
	}

	public void setFavoties(List<String> favoties) {
		this.favoties = favoties;
	}

	public Map<String, String> getMap() {
		return map;
	}

	public void setMap(Map<String, String> map) {
		this.map = map;
	}

	public Properties getProperties() {
		return properties;
	}

	public void setProperties(Properties properties) {
		this.properties = properties;
	}

	@Override
	public String toString() {
		return "Favorite{" +
				"favoties=" + favoties +
				", map=" + map +
				", properties=" + properties +
				'}';
	}
}

xml配置如下:

	<bean id="favorities" class="com.flexible.beans.Favorite">
		<property name="favoties">
			<list>
				<value>游泳</value>
				<value>足球</value>
				<value>籃球</value>
				<value>棒球</value>
			</list>
		</property>
		<property name="map">
			<map>
				<entry>
					<key><value>k1</value></key>
					<value>運動</value>
				</entry>
				<entry>
					<key><value>k2</value></key>
					<value>上班</value>
				</entry>
				<entry>
					<key><value>k3</value></key>
					<value>約會</value>
				</entry>
			</map>
		</property>
		<property name="properties">
			<props>
				<prop key="k1">value1</prop>
				<prop key="k2">value2</prop>
				<prop key="k3">value3</prop>
			</props>
		</property>
	</bean>
	<!--集合的合併-->
	<bean id="childFavorities" parent="favorities">
		<property name="favoties">
			<list merge="true">
				<value>賽車</value>
			</list>
		</property>
		<property name="map">
			<map merge="true">
				<entry>
					<key><value>k12</value></key>
					<value>運動2</value>
				</entry>
				<entry>
					<key><value>k22</value></key>
					<value>上班2</value>
				</entry>
				<entry>
					<key><value>k32</value></key>
					<value>約會2</value>
				</entry>
			</map>
		</property>
		<property name="properties">
			<props merge="true">
				<prop key="k12">value12</prop>
				<prop key="k22">value22</prop>
				<prop key="k32">value32</prop>
			</props>
		</property>
	</bean>

測試程式碼:

public class CollectionAttributeInject {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:iocdemo.xml");
		Favorite favorite = (Favorite) ctx.getBean("favorities");
		System.out.println(favorite.toString());
		Favorite childFavorities = (Favorite) ctx.getBean("childFavorities");
		System.out.println(childFavorities.toString());
	}
}

方法替換

Spring支援使用一個Bean的方法取替換另一個Bean的方法,替換別的Bean的Bean需要實現org.springframework.beans.factory.support.MethodReplacer介面,Spring利用該介面去替換目標Bean的方法.

被替換的類的方法:

public class Boss {
public House getHouse(){
House house = new House();
house.setHeight(1.0);
house.setLength(2.0);
house.setLength(3.0);
house.setWidth(4.0);
return house;
}
}

替換的類需要實現org.springframework.beans.factory.support.MethodReplacer介面。

public class Boss2 implements MethodReplacer{
	@Override
	public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {
		House house = new House();
		house.setHeight(1.01);
		house.setLength(2.01);
		house.setLength(3.01);
		house.setWidth(4.01);
		return house;
	}
}

xml配置檔案如下:

	<bean id="boss1" class="com.flexible.inject.methodreplace.Boss">
		<replaced-method name="getHouse" replacer="boss2"></replaced-method>
	</bean>
	<bean id="boss2" class="com.flexible.inject.methodreplace.Boss2"></bean>

<bean></bean>之間的關係

繼承

父<bean></bean>主要功能是簡化子<bean></bean>的配置,所以一般宣告未abstract="true",表示這個bean不例項化為一個對應的Bean。

例子:

xml配置如下:

	<!--這裡將這個bean宣告為abstract,表明它不會被例項化為bean-->
	<bean id="parent" class="com.flexible.beans.Parent" abstract="true">
		<property name="height" value="1.70"></property>
		<property name="weight" value="130"></property>
	</bean>
	<bean id="child" parent="parent">
		<property name="height" value="1.80"></property>
	</bean>

Parent.java

public class Parent {

	private String height;

	private String weight;

	public Parent() {
	}

	public String getHeight() {
		return height;
	}

	public void setHeight(String height) {
		this.height = height;
	}

	public String getWeight() {
		return weight;
	}

	public void setWeight(String weight) {
		this.weight = weight;
	}

	@Override
	public String toString() {
		return "Parent{" +
				"height='" + height + '\'' +
				", weight='" + weight + '\'' +
				'}';
	}
}

測試程式碼:

public class RelationBean {

	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:iocdemo.xml");
		Parent parent = (Parent) ctx.getBean("child");
		System.out.println(parent.toString());
	}
}

依賴

在配置中如果當前的Bean的初始化需要前置條件(即這些前置條件都得初始化完全了才能例項化這個Bean)滿足的時候,這個時候就需要使用到依賴 depends-on=""

引用

如果需要引用到另一個bean的id,需要使用<idref bean="xx"></idref>的方式使用,如果在同一個配置檔案可以使用<idref local="xx"></idref> 這樣在開發的時期就可以辨別出錯誤。

整合多哥配置檔案。

匯入其他配置檔案可以是import,例如:

<import resource="classpath:iocdemo2.xml"></import>

Bean作用域

低版本的Spring值支援兩種作用域,所以才有singleton="true|false"的配置方式。Spring為了向後相容,依然支援這種配置方式。推薦使用的配置方式:scope="<作用域型別>"

除了以上5種Bean作用域之外,Spring支援自定義Bean的作用域。通過org.springframework.beans.factory.config.Scope介面定義作用域,再通過org.springframework.beans.factory.config.CustomScopeConfigurer這個BeanFactoryPostprocessor註冊自定義的Bean作用域。

singleton

Spring將Bean預設的作用域都是singleton,並且將例項化的Bean快取再ApplicationContext的容器中,如果不希望例項化以開始就進行,可以使用lazy-init="true"實現懶載入,但是某些特殊的情況依然會提前載入。

prototype

scope="prototype"非單例作用域。它會將bean交給呼叫者,由呼叫者來管理bean的生命週期。

與Web應用環境相關的Bean作用域

<!--從類路徑下載入Spring配置檔案,classpath關鍵字特指類路徑下載入-->
  <!--這裡可以多個配置檔案,建議採用逗號隔開的方式-->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:flexible-context.xml</param-value>
	</context-param>
	<!--負責啟動Spring容器的監聽器,他將引用上面的上下檔案引數獲取Spring配置檔案的地址-->
   <!--該監聽器在web容器啟動時自動執行,它會根據contextConfigLocation
   Web容器引數獲取Spring配置檔案,並且啟動Spring容器。-->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

正常的情況我們只需要我們只需要通過ContextLoadListoner(或者ContextLoadServlet)將Web容器與Spring容器進行整合,但是如果需要使用request,session,globalSession這三個WEB相關的作用域,就需要也配置requestContextListiner(實現了ServletRequestListener監聽器介面),ContextLoadListener只是負責監聽容器的啟動和關閉。如果Spring需要request,session,globalSession的支援就需要獲取Web容器的HTTP請求事件,此時RequestContestListener就可以實現這個需求。

配置如下:

	<!--需要三大web容器作用域時需要這個配置-->
	<listener>
		<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
	</listener>

request:請求結束後,例項就會銷燬。 session:橫跨整個HTTPSession ,Session的所有HTTP請求共享同一個例項,HTTPSession結束後,例項銷燬。 globalSession作用域:globalSession作用域累死與session作用域,只能再Portlet的Web應用種使用。Portlet規範定義了全域性Session的概念,它被組成的Portlet Web應用所有子Portlet共享,如果不在Portlet Web應用的環境下,那麼globalSession==session作用域。

作用域依賴問題

需要啟用<aop:scoped-proxy></aop:scoped-proxy>

FactoryBean

一般情況下,Spring通過反射機制利用<bean></bean>的class屬性指定實現類例項化Bean。在某些情況下,例項化Bean的過程比較複雜,如果按照傳統的方式,需要提供大量的配置資訊。配置方式收到了限制。Spring為此提供了一個org.springframework.beans.factory.FactoryBean工廠類結論,使用者可可以通過實現改工廠類介面定製例項化Bean的邏輯。 例子: HouseFactoryBean.java

public class HouseFactoryBean implements FactoryBean<House> {
   Person person;

	public Person getPerson() {
		return person;
	}
	//接受引數
	public void setPerson(Person person) {
		this.person = person;
	}
	//例項化bean
	@Override
	public House getObject() throws Exception {
	   House house = new House();
	   house.setLength(1.0);
	   house.setWidth(2.0);
	   house.setHeight(3.0);
	   house.setPerson(person);
		return house;
	}
	//返回Hourse型別
	@Override
	public Class<House> getObjectType() {
		return House.class;
	}
	//比鬧事通FactoryBean返回的Bean是singleton
	@Override
	public boolean isSingleton() {
		return false;
	}

	@Override
	public String toString() {
		return "HouseFactoryBean{" +
				"person=" + person +
				'}';
	}
}

xml配置檔案

<bean id="hoursebean" class="com.flexible.beans.HouseFactoryBean">
    <property name="person">
        <bean id="personp" class="com.flexible.beans.Person">
            <property name="userAge" value="20"></property>
            <property name="userName" value="zhouqi"></property>
        </bean>
    </property>
</bean>

測試程式碼:

public static void main(String[] args) throws Exception {
    ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:iocdemo.xml");
    House house = (House) ctx.getBean("hoursebean");
    System.out.println(house.toString());
    //如果想拿到HouseFactoryBean例項,就需要 &hoursebean
    HouseFactoryBean houseFactoryBean = (HouseFactoryBean) ctx.getBean("&hoursebean");
    System.out.println(houseFactoryBean.toString());
    House object = houseFactoryBean.getObject();
    System.out.println(object.toString());
}

執行結果:

House{length=1.0, width=2.0, height=3.0, person=Person{userName='zhouqi', userAge=20}}
HouseFactoryBean{person=Person{userName='zhouqi', userAge=20}}
House{length=1.0, width=2.0, height=3.0, person=Person{userName='zhouqi', userAge=20}}

基於註解的配置

使用註解定義Bean

Spring提供了四個定義Bean的註解,分別是:

[email protected]:用於對DAO實現類進行標註

[email protected]:用於對Service實現類進行標註。

[email protected]:用於對Controller實現類進行標註

[email protected]可以代替上面任何一個,只不過上面這些標註有特殊的用途,能一目瞭然的看出來這個bean的用途。

掃描註解定義的Bean

Spring提供了一個Context名稱空間,它提供了通過掃面類包以應用註解定義Bean的方式。 例如:<context:component-scan base-package="com.flexible"></context:component-scan>

如果希望掃描的是特定的類而非基礎包下的類,可以使用resource-pattern熟悉過濾

	<context:component-scan base-package="com.flexible" resource-pattern="xx/*.class"></context:component-scan>

如果還需要更加具體的過濾,如實現了xx介面的,

例如:

	<context:component-scan base-package="com.flexible">
		<context:include-filter type="aspectj" expression="com.flexible..*Controller+"></context:include-filter>
	</context:component-scan>

自動裝配

使用 @Autoired

@Qualifier知道注入的Bean的名稱。

對標準註解的@Resource(需要提供一個Bean的名字)和@Inject的支援。

Bean作用範圍及生命過程的方法。

@Scope("prototype")

Bean作用範圍以及生命過程方法

在使用<bean></bean>進行配置時,可以通過init-method和destroy-method屬性指定Bean的初始化以及容器銷燬前執行的方法。Spring從2.5開始支援JSR-250中定義的@PostConstruct和@PreDestroy註解,在Spring中他們相當於init-method和destroy-method屬性的功能,不過在使用註解時,可以在一個Bean中定義多個@PostConstruct和@PreDestroy方法。

例子:

LifeCyleBea.java

@Component
public class LifeCyleBean {
	private String info;
	@PostConstruct
	public void initMethod(){
		System.out.println(".....this is initMethod....");
	}
	@PreDestroy
	public void destroyMethod(){
		System.out.println(".....this is destroyMethod....");
	}

	public String getInfo() {
		return info;
	}

	public void setInfo(String info) {
		this.info = info;
	}
}

xml配置檔案開啟包掃描:

	<context:component-scan base-package="com.flexible">
	</context:component-scan>

測試程式碼:

public class LifeCycleDemo {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("classpath:iocdemo.xml");
		((ClassPathXmlApplicationContext)context).destroy();

	}
}

執行結果: .....this is initMethod....

.....this is destroyMethod....

基於Java類的配置

使用Java類提供的Bean定義資訊

JavaConfig是Spring的一個子專案,旨在通過Java類的方式提供Bean的定義資訊,在Spring2.0開始釋出。普通的POJO只有標註@Configuration註解,就可以為Spring容器提供Bean定義的資訊。每個標註了@Bean得類方法都相當於提供了一個Bean的定義資訊。通過程式碼進行配置要靈活點,但是配置檔案配置要簡潔些。

AppConfig.java

//將一個POJO標註為定義Bean的配置類
@Configuration
public class AppConfig {
//可以給bean一個名字,還可以配置作用域
//@Bean(name = "car")
@Bean
public Car getCar(){
	Car car = new Car();
	car.setPerson(getPerson());
	return car;
}
@Bean
public Person getPerson(){
	 Person person = new Person();
	 person.setUserName("王八");
	 person.setUserAge(28);
	 return person;
}
}

測試程式碼:

    ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
    Car car = (Car) context.getBean(Car.class);
    System.out.println(car.toString());

使用基於Java類的配置資訊啟動Spring容器

1.直接通過@Configuration類啟動Spring容器

Spring提供了一個AnnotationConfigApplicationContext類,它能夠直接通過標註¥Configuration的Java啟動Spring容器。 例如:

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

AnnotationConfigApplicationContext還支援通過編碼的方式載入多個@Configuration配置類,然後重新整理容器應用的配置類。 例如:

ApplicationContext context = new AnnotationConfigApplicationContext();
context.register(AppConfig.class);
context.register(AppConfig2.class);
context.refresh()

通過XML配置檔案引用@Configuration的配置

標註了@Configuration的配置類與標註了@Component的類一樣也是一個Bean,它可以被Spring的context:compent-scan</context:compent-scan>掃描到相應的配置類即可。 例如:

<context:component-scan base-package="com.flexible" resource-pattern="AppConfig.class">

通過@Configuration配置類引用XML配置資訊

在@Configuration配置類中可以通過@ImportResource引入XML配置檔案,在RefXmlConfig配置類中即可直接通過@Autowired引用XML配置檔案定義的Bean. RefXmlConfig.java

@Configuration
@ImportResource("classpath:iocdemo2.xml")
public class RefXmlConfig {
@Bean
@Autowired
public PenBox getPenBox(PenBox penBox){
	return penBox;
}
}

PenBox.java

public class PenBox {

private String markName;

private String description;

	public PenBox() {
	}

	public String getMarkName() {
		return markName;
	}

	public void setMarkName(String markName) {
		this.markName = markName;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@Override
	public String toString() {
		return "PenBox{" +
				"markName='" + markName + '\'' +
				", description='" + description + '\'' +
				'}';
	}
}

測試程式碼:

public class RefXmlDemo {
	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(RefXmlConfig.class);
		PenBox penBox = (PenBox) context.getBean("penBox");
		System.out.println(penBox.toString());
	}
}

執行結果:

PenBox{markName='xxx', description='description'}