Spring依赖注入
依赖注入是IoC特性的一个重要功能,能自动将需要的Bean注入到对应的属性中,不需要手动进行初始化对象。
注入对象的方式主要有以下几种:
- Set注入
- 构造器注入
本文主要讲解Spring依赖注入的基本类型及来源。
本文所示案例基于Spring依赖查找代码结构,maven依赖配置略。
1.注入的类型
1.1 根据名称进行注入
定义一个仓储类UserRepository,如下:
public class UserRepository {
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
在META-INF目录下新增spring-ioc-injection.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="spring-ioc-overview.xml" />
<bean id="userRepository" class="com.vielat.spring.ioc.injection.repository.UserRepository">
<property name="users">
<list>
<ref bean="user" />
<ref bean="adminUser" />
</list>
</property>
</bean>
</beans>
在上一篇Spring依赖查找中,我们定义了两个对象:user和adminUser。这里直接新建一个配置文件,将上述配置通过import的方式进行引入。然后定义userRepository对象,属性值配置一个list,分别指向两个用户对象的引用。
测试类如下:
public class IoCInjectionDemo {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/spring-ioc-injection.xml");
UserRepository userRepository = (UserRepository) beanFactory.getBean("userRepository");
System.out.println(userRepository.getUsers());
}
}
1.2 根据类型进行注入
上述根据名称进行注入,是通过引用Bean的名称的形式进行注入,但是这种方式是一种硬编码的形式。Spring提供了一种自动注入的方式,如下:
<bean id="userRepository" class="com.vielat.spring.ioc.injection.repository.UserRepository" autowire="byType">
<!--<property name="users">
<list>
<ref bean="user" />
<ref bean="adminUser" />
</list>
</property>-->
</bean>
通过autowire="byType"属性,Spring能自动查找该属性类型的Bean并进行注入,不需要手动配置注入的方式。
2. 注入的来源
我们了解了基本的注入之后,一定会比较疑惑:Spring注入的Bean从哪里来?以下从3个方面来讲述。
2.1 注入自定义Bean
以上述xml为例,定义的user、adminUser都属于自定义的Bean
2.2 注入非Spring Bean
在UserRepository
中新增如下属性:
public class UserRepository {
...
private BeanFactory beanFactory;
...
public BeanFactory getBeanFactory() {
return beanFactory;
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}
配置文件不变,还是根据类型自动进行注入。在测试类中输入此对象:
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/spring-ioc-injection.xml");
UserRepository userRepository = (UserRepository) beanFactory.getBean("userRepository");
// System.out.println(userRepository.getUsers());
System.out.println(userRepository.getBeanFactory());
System.out.println(beanFactory);
System.out.println(userRepository.getBeanFactory() == beanFactory);
}
输出结果如下:
org.springframework.beans.factory.support.DefaultListableBeanFactory@22f71333: defining beans [user,adminUser,objectFactory,userRepository]; root of factory hierarchy
org.springframework.context.support.ClassPathXmlApplicationContext@7e6cbb7a, started on Wed Jan 04 22:15:55 CST 2023
false
从上述执行结果可以看出,Spring自动注入的BeanFactory是一个内建的Bean,并不是我们自己初始化的BeanFactory。
如果通过我们初始化的容器BeanFactory去获取BeanFactory是获取不到的。
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/spring-ioc-injection.xml");
System.out.println(beanFactory.getBean(BeanFactory.class));
}
运行结果如下:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.beans.factory.BeanFactory' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1126)
2.3 注入内建的Bean
在UserRepository新增如下属性:
public class UserRepository {
...
private ObjectFactory<User> objectFactory;
private ObjectFactory<ApplicationContext> applicationContextObjectFactory;
...
public ObjectFactory<User> getObjectFactory() {
return objectFactory;
}
public void setObjectFactory(ObjectFactory<User> objectFactory) {
this.objectFactory = objectFactory;
}
public ObjectFactory<ApplicationContext> getApplicationContextObjectFactory() {
return applicationContextObjectFactory;
}
public void setApplicationContextObjectFactory(ObjectFactory<ApplicationContext> applicationContextObjectFactory) {
this.applicationContextObjectFactory = applicationContextObjectFactory;
}
}
测试类如下:
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/spring-ioc-injection.xml");
UserRepository userRepository = (UserRepository) beanFactory.getBean("userRepository");
ObjectFactory objectFactory = userRepository.getObjectFactory();
System.out.println(objectFactory.getObject());
ObjectFactory applicationContextObjFactory = userRepository.getApplicationContextObjectFactory();
System.out.println(applicationContextObjFactory.getObject());
System.out.println(applicationContextObjFactory.getObject() == beanFactory);
System.out.println(beanFactory.getBean(Environment.class));
}
输出结果如下:
AdminUser{address='广州'} User{id=1, name='Michael'}
org.springframework.context.support.ClassPathXmlApplicationContext@7e6cbb7a, started on Wed Jan 04 22:29:23 CST 2023
true
StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[PropertiesPropertySource {name='systemProperties'}, SystemEnvironmentPropertySource {name='systemEnvironment'}]}
这次注入的ApplicationContext就是我们自己初始化出来的容器对象。
上一篇:Spring依赖查找