Spring支持三种类型的bean配置:
1.xml;
2.自动装配;
3.java config;
下面分别看下。
xml方式:
分为 基于构造方法的和基于属性的注入。
首先定义一个xml文件存放bean的定义,每一个bean都用标签<bean>来表示,里面要有bean的类型,一般是类名的全限定。可选的是bean的name,一般都要指定,这是比较好的做法,但是如果不指定,bean会有一个默认的名字,就是全限定类名+#编号。举个例子,类名是“com.abc.model.Address”,则该类的第一个不带name属性的bean的名字就是“com.abc.model.Address#0”,bean越多,数字会累加。一般使用的时候还是要加上name,可读性更好。
先来看基于构方法的。使用constructor-arg来注入属性,这有四种方式。
1.只有value或者ref属性,那么会按照配置的顺序依次为构造方法注入值,这种的务必保证配置顺序与构造方法参数顺序保持一致;
2.使用index属性来指定参数顺序;
3.使用type属性来指定类型,spring会按照类型来匹配参数;
4.使用name属性来指定参数名,这个是比较常用的方式。
如果要注入一个字面量使用value,注入引用使用ref,注入null使用<null/>。
使用构造方法注入,务必保证有与配置一致的构造方法存在,否则无法注入。
再来看基于属性的注入。
使用property标签和name属性。这里会调用无参构造方法,必须提供。
下面是一个例子:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name = "addr1" class="com.abc.model.Address">
<constructor-arg value="yuanping"></constructor-arg>
</bean>
<bean class="com.abc.model.Address">
<constructor-arg value="shanxi"></constructor-arg>
</bean>
<bean id = "p1" class="com.abc.model.Person">
<constructor-arg value="liyao"/>
<constructor-arg value="25"/>
<constructor-arg>
<list>
<ref bean="addr1"></ref>
<ref bean="com.abc.model.Address#0"></ref>
</list>
</constructor-arg>
</bean>
<bean id = "p2" class="com.abc.model.Person">
<constructor-arg name = "age" value="24"/>
<constructor-arg name = "name" value="liyao"/>
<constructor-arg name="address">
<null/>
</constructor-arg>
</bean>
<bean id = "p3" class="com.abc.model.Person">
<constructor-arg type="int" value="24"/>
<constructor-arg type="java.lang.String" value="liyao"/>
<constructor-arg type="java.util.List">
<list>
<ref bean="addr1"></ref>
<ref bean="com.abc.model.Address#0"></ref>
</list>
</constructor-arg>
</bean>
<bean id = "p4" class="com.abc.model.Person">
<constructor-arg index="1" value="24"/>
<constructor-arg index="0" value="liyao"/>
<constructor-arg index="2">
<list>
<ref bean="addr1"></ref>
<ref bean="com.abc.model.Address#0"></ref>
</list>
</constructor-arg>
</bean>
<bean id = "p5" class="com.abc.model.Person">
<property name="age" value="24"></property>
<property name="address">
<list>
<ref bean="addr1"></ref>
<ref bean="com.abc.model.Address#0"></ref>
</list>
</property>
<property name="name" value="liyao"></property>
</bean>
</beans>
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Person p1 = (Person)applicationContext.getBean("p1");
System.out.println(p1);
Person p2 = (Person)applicationContext.getBean("p2");
System.out.println(p2);
Person p3 = (Person)applicationContext.getBean("p3");
System.out.println(p3);
Person p4 = (Person)applicationContext.getBean("p4");
System.out.println(p4);
Person p5 = (Person)applicationContext.getBean("p5");
System.out.println(p5);
输出为:
Person{name='liyao', age=25, address=[Address{addr='yuanping'}, Address{addr='shanxi'}]}
Person{name='liyao', age=24, address=null}
Person{name='liyao', age=24, address=[Address{addr='yuanping'}, Address{addr='shanxi'}]}
Person{name='liyao', age=24, address=[Address{addr='yuanping'}, Address{addr='shanxi'}]}
Person{name='liyao', age=24, address=[Address{addr='yuanping'}, Address{addr='shanxi'}]}
下面看自动装配方式:
这里涉及到两个概念,一个是扫描bean,自动加入容器管理,另一个是自动为bean注入属性。
扫描bean需要在xml文件中加上配置:
<context:component-scan base-package="com.abc.model"/>
指定要扫描的位置,尽量精确范围,减少不必要的扫描。
然后使用@Component注解,让spring把实例自动加入容器管理。
注入属性可以为属性添加@Autowired注解,这样当实例化这个bean时,就会自动用容器内合适的bean来设置属性。一个简单的例子:
@Component
public class Door {
public void open(){
System.out.println("open door");
}
}
@Component
public class House {
@Autowired
public Door door;
}
public static void main(String args[]) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
House h = (House) applicationContext.getBean("house");
h.door.open();
}
当然关于@Autowired还要歧义的问题需要考虑。