小马哥讲Spring核心编程思想-spring ioc 容器概述
前言
转眼间,已经2024年了,已经快一年没写过博客了,这一年学习的进度减慢了,好多内容学习了也没记录,学了不久好像就忘记了,还是得记录记录,趁着公司的“极客时间”学习福利,赶紧找点有含金量的课程提升提升 ^ . ^,虽然前面已经学习过一些spring源码的课程,但感觉还是不够深入,因此,选择了该课程进行学习
一、依赖查找的几种方式
准备:
// 配置 XML 配置文件
// 启动 Spring 应用上下文
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-lookup-context.xml");
1、实时查找
- 按类型查询
- 按名称查找
如代码
User user = beanFactory.getBean(User.class);
System.out.println("按类型:" + user);
/*----------*/
User user = (User) beanFactory.getBean("user");
System.out.println("按名称:" + user);
/*----------*/
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = listableBeanFactory.getBeansOfType(User.class);
System.out.println("查找到的所有的 User 集合对象:" + users);
/*----------*/
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) beanFactory;
Map<String, User> users = (Map) listableBeanFactory.getBeansWithAnnotation(Super.class);
System.out.println("按注解:查找标注 @Super 所有的 User 集合对象:" + users);
2、延时查找
xml配置:
<bean id="objectFactory" class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<property name="targetBeanName" value="user"/>
</bean>
ObjectFactory<User> objectFactory = (ObjectFactory<User>) beanFactory.getBean("objectFactory");
User user = objectFactory.getObject();
System.out.println("延迟查找:" + user);
二、依赖注入的几种方式
准备:先通过xml配置两个user对象,如下
<bean id="user" class="org.geekbang.thinking.in.spring.ioc.overview.domain.User">
<property name="id" value="1"/>
<property name="name" value="xz"/>
</bean>
<bean id="superUser" class="org.geekbang.thinking.in.spring.ioc.overview.domain.SuperUser" parent="user"
primary="true">
<property name="address" value="杭州"/>
</bean>
1、根据 Bean 名称注入
<bean id="userRepository" class="org.geekbang.thinking.in.spring.ioc.overview.repository.UserRepository">
<!-- 手动配置 -->
<property name="users">
<util:list>
<!-- 按名称注入上述的两个bean -->
<ref bean="superUser" />
<ref bean="user" />
</util:list>
</property>
</bean>
2、根据 Bean 类型注入
<!-- autowire="byType":按类型注入上述的两个bean,顺序为bean配置的顺序 -->
<bean id="userRepository" class="org.geekbang.thinking.in.spring.ioc.overview.repository.UserRepository"
autowire="byType">
</bean>
3、注入容器内建 Bean、非Bean 对象
当我们在自己的类中增加一个容器的类属性,如:
private Environment environment; // 内建 Bean
private BeanFactory beanFactory; // 内建 非Bean
配置我们自己的bean时,容器会自动将 两个bean 注入到我们的bean中
为什么 BeanFactory 叫非bean对象,因为我们不能通过依赖查找的方式获取,但能帮你注入,如下会报错,但获取 Environment 则不会:
System.out.println(beanFactory.getBean(BeanFactory.class));
由此得出,依赖查找和依赖注入的bean来自不同的地方
4、延时注入
和延迟查找类似,注入 ObjectFactory ,在通过 ObjectFactory 获取 User
private ObjectFactory<User> objectFactory;
三、依赖的来源
1、自定义 Bean
通过xml配置、@Bean、@Componet等注解、Properties 文件、java API产生的bean
2、容器内建 Bean 对象
不是自定义的,能帮我们自动注入或能通过 beanFactory.getBean(xxx.class) 获取的,如上述的 Environment
3、容器内建依赖(非Bean)
能帮我们自动注入,但不能通过 beanFactory.getBean(xxx.class) 获取的,如 BeanFactory
四、BeanFactory和ApplicationContext
1、区别
你可以使用以下两种方式获取xml上下文配置:
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
先给出答案,其实 BeanFactory 就是 ApplicationContext,只是两者为不同的对象,spring官网对其有介绍,简单理解:BeanFactory是spring的底层容器,ApplicationContext是BeanFactory的超集,在其基础上引入了 aop整合、国际化、事物发布等,更方便大家的使用,如图,采用组合的方式将其引入:
你可能在想,我是该用 BeanFactory 还是 ApplicationContext,其实都可以,只是 ApplicationContext 的支持更丰富,更贴近于实际开发。
五、spring IOC 容器的生命周期
这里已经学习过相关内容了,不再记录,文章链接:https://blog.csdn.net/weixin_44227063/article/details/121734371