文章目录
Spring IoC依赖注入:Spring提供了哪些依赖注入模式和类型呢?
00、代码实现参考包的路径
1、context-dependency-injection.xml
2、DependencyInjectionDemo.java
3、其他同上节引用一致
01、根据Bean名称注入
-
首先需要创建一个UserRepository,用于存储依赖注入的Bean对象
-
import com.markus.spring.ioc.dependency.domain.User; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ObjectFactory; import org.springframework.context.ApplicationContext; import java.util.Collection; /** * @author 14222 * @date 2021-02-02 22:10 */ public class UserRepository { private Collection<User> users; public Collection<User> getUsers() { return users; } public void setUsers(Collection<User> users) { this.users = users; } }
-
-
xml文件配置,将users集合类型注入到UserRepository当中去
-
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd"> <import resource="context-dependency-lookup.xml"/> <bean id="userRepository" class="com.markus.spring.ioc.dependency.repository.UserRepository"> <property name="users"> <util:list> <ref bean="user"/> <ref bean="super"/> </util:list> </property> </bean> </beans>
-
-
写一个查看注入是否成功的Demo
-
import com.markus.spring.ioc.dependency.repository.UserRepository; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.env.Environment; /** * @author 14222 * @date 2021-02-02 22:07 */ public class DependencyInjectionDemo { public static void main(String[] args) { //1.配置 xml 文件 //2.启动 Spring 应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-injection.xml"); UserRepository repository = beanFactory.getBean(UserRepository.class); System.out.println(repository.getUsers()); } }
-
这里有个小的知识点:users集合中User实例的顺序问题,这取决于xml文件里配置的先后顺序,比如我将xml文件里的顺序调换一下,结果会是下图所示
-
所以,会有这样一个问题:注入容器的Bean是否可以调换顺序,答案是否定的,一旦在xml文件中的顺序确定,那么就会固定,不能调换!
-
02、根据Bean类型注入
01章节讲述的注入方式其实是属于硬编码方式,如果想要注入多个user对象,那么需要继续写代码注入相应的Bean。接下来,我们接触一个新的 Bean便签里的元信息:autowire。
该小结解释的是根据Bean类型注入,所以我们选择byType;
-
代码演示:
-
在01小结的基础上,只需要改变xml文件中的信息即可
-
<bean id="userRepository" class="com.markus.spring.ioc.dependency.repository.UserRepository" autowire="byType"> <!-- <property name="users">--> <!-- <util:list>--> <!-- <ref bean="user"/>--> <!-- <ref bean="super"/>--> <!-- </util:list>--> <!-- </property>--> </bean>
-
03、注入非Bean对象(依赖)
上两个小节讲述了 通过硬编码或者自动注入的方式注入Bean对象,那接下来我们尝试注入一下BeanFactory,更新我们的UserRepository
public class UserRepository {
private Collection<User> users;
private BeanFactory beanFactory;
public BeanFactory getBeanFactory() {
return beanFactory;
}
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public Collection<User> getUsers() {
return users;
}
public void setUsers(Collection<User> users) {
this.users = users;
}
}
-
代码演示:
-
public class DependencyInjectionDemo { public static void main(String[] args) { //1.配置 xml 文件 //2.启动 Spring 应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-injection.xml"); UserRepository repository = beanFactory.getBean(UserRepository.class); // System.out.println(repository.getUsers()); System.out.println(repository.getBeanFactory() == beanFactory); } }
-
按照我们想的,控制台打印的应该是 True,但实际上是false。那到底是为什么呢?我们先更新下Demo代码,将UserRepository中注入的BeanFactory类型打印出来
-
先留着这个疑问,接下来,我们再尝试向UserRepository中注入一个ObjectFactory,也就是通过类型注入时采用延迟注入。
-
public class UserRepository { XXXX; private ObjectFactory<ApplicationContext> objectFactory; public ObjectFactory<ApplicationContext> getObjectFactory() { return objectFactory; } public void setObjectFactory(ObjectFactory<ApplicationContext> objectFactory) { this.objectFactory = objectFactory; } XXXX; }
-
我们来看下这个注入的上下文Bean和BeanFactory是否是同一个实例对象;
-
答案是肯定的。也就是说 真正注入的BeanFactory的实例对象其实就是引入的外部依赖,而如果我们采用依赖查找的方式去查找BeanFactory时,是会出现异常的,我们来实验一遍。
-
继续更新Demo代码
-
public class DependencyInjectionDemo { public static void main(String[] args) { //1.配置 xml 文件 //2.启动 Spring 应用上下文 BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/context-dependency-injection.xml"); System.out.println(beanFactory.getBean(BeanFactory.class)); } }
-
所以,该实验验证我们上面的想法,真正注入到IoC容器的BeanFactory实例其实是外部依赖,而非Bean对象。而我们上面留有的那个疑问:注入的BeanFactory和我们使用的BeanFactory并非是同一个。
-
-
看到这里,也许大家会有一个疑问?IoC容器中注入的对象除了Bean对象,还有外部依赖,那Spring IoC依赖来源到底在哪呢?这个疑问我们在下节会做出解释,欢迎大家继续来跟着我探究,依赖注入和查找的对象到底来自于哪里?