一、配置Bean的两种方式之使用XML配置Bean
1.Bean的自动装配
public class Person { private String name; private Mobile mobile; public String getName() { return name; } public void setName(String name) { this.name = name; } public Mobile getMobile() { return mobile; } public void setMobile(Mobile mobile) { this.mobile = mobile; } @Override public String toString() { return "Person [name=" + name + "]"; } }
public class Mobile { private String brand; private double price; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "Mobile [brand=" + brand + ", price=" + price + "]"; } }
在IOC容器中配置byName自动装配:
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="mobile" class="com.spring.model.Mobile"> <property name="brand" value="iphone"></property> <property name="price" value="5000"></property> </bean> <bean id="person" class="com.spring.model.Person" autowire="byName"> <property name="name" value="loose"></property> </bean> </beans>
byName: 若属性名和某一个 bean 的 id 名一致, 即可完成自动装配. 若没有 id 一致的, 则无法完成自动装配
在IOC容器中配置byType自动装配:
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 无需id,根据Bean的类型自动装配 --> <bean class="com.spring.model.Mobile"> <property name="brand" value="iphone"></property> <property name="price" value="5000"></property> </bean> <bean id="person" class="com.spring.model.Person" autowire="byType"> <property name="name" value="loose"></property> </bean> </beans>
byType: 根据类型进行自动装配. 但要求 IOC 容器中只有一个类型对应的 bean, 若有多个则无法完成自动装配
public class Person { private String name; private String province; private String city; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } @Override public String toString() { return "Person [name=" + name + ", province=" + province + ", city=" + city + "]"; } }
接着在IOC容器中配置该Bean的信息:
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="personParent" class="com.spring.model.Person"> <property name="name" value="loose"></property> </bean> <!-- 使用parent声明继承哪个Bean的配置 --> <bean id="personSon" parent="personParent"></bean> </beans>
测试简单继承程序:
public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person = (Person) ctx.getBean("personSon"); System.out.println(person); //输出:Person [name=loose, province=null, city=null] } }
在IOC容器中配置子Bean覆盖父Bean的信息:
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="personParent" class="com.spring.model.Person"> <property name="name" value="loose"></property> </bean> <bean id="personSon" parent="personParent">
<!-- 覆盖父Bean的name属性 --> <property name="name" value="loose2"></property> </bean> </beans>
测试子Bean覆盖父Bean程序:
public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person = (Person) ctx.getBean("personSon"); System.out.println(person); //输出:Person [name=loose2, province=null, city=null] } }
在IOC容器中将父Bean定义为模板:
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <!-- 定义为模板可以不配置class属性,但子Bean必须配置class --> <bean id="personParent" abstract="true"> <property name="name" value="loose"></property> </bean> <bean id="personSon" class="com.spring.model.Person" parent="personParent"></bean> </beans>
测试将父Bean定义为模板程序:
public class Main { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person = (Person) ctx.getBean("personSon"); System.out.println(person); //输出:Person [name=loose2, province=null, city=null] } }
3.Bean的依赖配置
public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person [name=" + name + "]"; } }
在IOC容器中,将该Bean配置为单例:
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="person" class="com.spring.model.Person" scope="singleton"> <property name="name" value="loose"></property> </bean> </beans>
测试Bean单例:
public class Main { @SuppressWarnings("resource") public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person1 = (Person) ctx.getBean("person"); Person person2 = (Person) ctx.getBean("person"); System.out.println(person1 == person2); //输出true,证明是单例子 } }
在IOC容器中,将该Bean配置为prototype类型:
<?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:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="person" class="com.spring.model.Person" scope="prototype"> <property name="name" value="loose"></property> </bean> </beans>
测试Bean prototype:
public class Main { @SuppressWarnings("resource") public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person1 = (Person) ctx.getBean("person"); Person person2 = (Person) ctx.getBean("person"); System.out.println(person1 == person2); //输出false,证明非单例 } }
上面的例子仅仅是获取两个id一致的Bean,比较无法直观的看出IOC容器为我们的Bean创建实例的过程,接下来,我们通过一个例子再来看单例和prototype的区别:我们将Person的无参构造器显示出来
public class Person { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public Person() { System.out.println("我是person无参构造器"); } @Override public String toString() { return "Person [name=" + name + "]"; } }
接着将IOC容器中的Bean配置为单例模式:
<bean id="person" class="com.spring.model.Person" scope="singleton"> <property name="name" value="loose"></property> </bean>
测试单例,看看控制台的输出:
public class Main { @SuppressWarnings("resource") public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //运行后输出:我是person无参构造器 } }
说明:单例模式是IOC一启动就帮我们实例化了Person。
再将Bean配置为prototype,然后在看测试程序的控制台输出:
<bean id="person" class="com.spring.model.Person" scope="prototype"> <property name="name" value="loose"></property> </bean>
public class Main { @SuppressWarnings("resource") public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); //运行后输出:没有任何输出 } }
说明:prototype模式,IOC容器启动并不会帮我们实例化Person。
最后,我们通过获取Bean再来对比下两者的区别:
<bean id="person" class="com.spring.model.Person" scope="singleton"> <property name="name" value="loose"></property> </bean>
public class Main { @SuppressWarnings("resource") public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); Person person1 = (Person) ctx.getBean("person"); Person person2 = (Person) ctx.getBean("person"); System.out.println(person1 == person2); //运行后输出: //我是person无参构造器 //true } }
<bean id="person" class="com.spring.model.Person" scope="prototype"> <property name="name" value="loose"></property> </bean>
public class Main { @SuppressWarnings("resource") public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); System.out.println("前面没有帮忙实例化..."); Person person1 = (Person) ctx.getBean("person"); Person person2 = (Person) ctx.getBean("person"); System.out.println(person1 == person2); //运行后输出: //我是person无参构造器 //我是person无参构造器 //false } }
总结:
单例模式的Bean,IOC容器启动会自动帮我们创建了该Bean的实例,并且只创建一次;而prototype模式下IOC容器启动不会帮我们创建该Bean的实例,而是每次去getBean的时候,每次都实例化一个对象出来。
注意:常用的是单例和prototype模式,其它的了解就行,有兴趣的自行翻阅资料。