不了解IoC中Bean注入的,可以先看看前一篇
Spring中Bean的注册
先创建一个类。
public class User {
private Integer age;
private String name;
private String[] favorites;
private Cat cat;
private List<Dog> dogs;
private Properties job;
private Map info;
//省略get set 等方法
}
Set方法注入
<bean class="com.tongzhou.demo.User" id="user">
<property name="age" value="18"/>
<property name="name" value="张三"/>
<property name="cat" ref="cat01"/>
<property name="dogs">
<list>
<ref bean="dog"/>
<bean class="com.tongzhou.demo.Dog" >
<property name="name" value="小黑"/>
</bean>
</list>
</property>
<property name="favorites">
<array>
<value>足球</value>
<value>篮球</value>
</array>
</property>
<property name="job">
<props>
<prop key="salary">12000</prop>
<prop key="position">工程师</prop>
</props>
</property>
</bean>
这里通过反射赋值,本质上就是通过set方法进行赋值。
构造器注入
<bean class="com.tongzhou.demo.User" id="user">
<constructor-arg name="age" value="18"/>
<constructor-arg name="cat" ref="cat"/>
<constructor-arg name="dogs">
<list>
<ref bean="dog"/>
<bean class="com.tongzhou.demo.Dog" id="dog2">
<property name="name" value="小蓝"/>
</bean>
</list>
</constructor-arg>
<constructor-arg name="favorites">
<array>
<value>篮球</value>
<value>钢琴</value>
</array>
</constructor-arg>
<constructor-arg name="info">
<map>
<entry key="address" value="广州"/>
</map>
</constructor-arg>
<constructor-arg name="job">
<props>
<prop key="salary">12000</prop>
</props>
</constructor-arg>
<constructor-arg name="name" value="张三"/>
</bean>
自动注入
bean中autowire属性,默认是no,意思就是不进行自动注入
byName:分析当前bean的属性,去Spring容器中查找同名的属性。
byType:分析当前bean的类型,去Spring容器中查找同类型的属性。
constructor:寻找合适的构造方法,进行注入。
default:使用父标签的属性进行注入。
default案例
<beans default-autowire="byName">
<bean class="com.tongzhou.demo.Cat" id="cat">
<property name="name" value="小黄"/>
</bean>
<bean class="com.tongzhou.demo.Cat" id="cat2">
<property name="name" value="小黑"/>
</bean>
<bean class="com.tongzhou.demo.User" id="user" autowire="default">
</bean>
</beans>
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("spring_autoware.xml");
User bean = classPathXmlApplicationContext.getBean(User.class);
System.out.println(bean);
这里可以看出来,通过byName,则名称相同的只有一个bean,所以只自动注入了第一个bean。
Java配置
public class JavaConfig {
@Bean
Person person(){
Person person = new Person();
person.setAge(18);
person.setName("李四");
return person;
}
}
注意,我这里暂时没有加@Configurable注解,这里是不影响的。
默认情况下,方法名就是bean名,bean中可重命名。
AnnotationConfigApplicationContext javaConfig = new AnnotationConfigApplicationContext(JavaConfig.class);
Person person = javaConfig.getBean("person", Person.class);
System.out.println(person);
需要自定义名称,则可以在bean注解中进行改名。
@Bean("person")
那如果有多个类注入,并且需要相互依赖呢?
则可以通过如下的方式实现。
@Bean("person")
Person person(Dog dog){
Person person = new Person();
person.setAge(18);
person.setName("李四");
person.setDog(dog);
return person;
}
@Bean
Dog dog(){
Dog dog = new Dog();
dog.setName("小黑");
return dog;
}
调用
AnnotationConfigApplicationContext javaConfig = new AnnotationConfigApplicationContext(JavaConfig.class);
Person person = javaConfig.getBean("person", Person.class);
Dog dog = javaConfig.getBean("dog", Dog.class);
System.out.println(person.getDog() == dog);
结果,自然是true.
需要注意的是,Spring容器在加载的时候,会先在容器中寻找,依赖度bean有没有进行注册,如果有,则直接可以关联上,而如果通过再次实例化的方式,则获得的bean就不是同一个bean。
@Bean("person")
Person person(){
Person person = new Person();
person.setAge(18);
person.setName("李四");
Dog dog = new Dog();
person.setDog(dog);
return person;
}
@Bean
Dog dog(){
Dog dog = new Dog();
dog.setName("小黑");
return dog;
}
调用
AnnotationConfigApplicationContext javaConfig = new AnnotationConfigApplicationContext(JavaConfig.class);
Person person = javaConfig.getBean("person", Person.class);
Dog dog = javaConfig.getBean("dog", Dog.class);
System.out.println(person.getDog() == dog);
结果自然是false.