(1)官方文档描述
(2)BeanFactory和ApplicationContext的关系
package org.binsoft.thinking.in.spring.ioc.overview.dependency.injection;
import org.binsoft.thinking.in.spring.ioc.overview.annotation.Super;
import org.binsoft.thinking.in.spring.ioc.overview.domain.User;
import org.binsoft.thinking.in.spring.ioc.overview.repository.UserRepository;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.Environment;
import java.util.Map;
/**
* 依赖注入示例
*
* @author binsoft
* @version 1.0
* @date 2021/1/1 11:53
*/
public class DependencyInjectionDemo {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/dependency-injection-context.xml");
UserRepository userRepository = beanFactory.getBean("userRepository", UserRepository.class);
System.out.println(userRepository.getBeanFactory() == beanFactory); // false
}
}
上面的代码中,既然ApplicationContext is a sub-interface of BeanFactory,那么serRepository.getBeanFactory() == beanFactory的输出结果为何为false?
第一步:分析ClassPathXmlApplicationContext的类图:
找到可写的(Configurable)应用上下文对象ConfigurableApplicationContext接口,
看看是否有setBeanFactory的方法
没有setBeanFactory的相关方法
但是里面有个getBeanFactory方法:
那么这个BeanFactory是如何设置进来的呢?
第二步:找到org.springframework.context.support.AbstractRefreshableApplicationContext类
BeanFactory是组合进来的,并不是完完全全的去抽象或继承的。
并通过getBeanFactory()方法来获取到组合进来的ConfigurableListableBeanFactory。
那么AbstractApplicationContext在getBean()的时候,而是通过这个代理的BeanFactory去查找对象,它并不是自己具备这个能力,而是通过组合的BeanFactory去完成。
结论:BeanFactory和 ApplicationContext 其实是同一类事物,只不过在底层实现的时候,ApplicationContext组合了一个BeanFactory的实现,所以上面的示例代码中ApplicationContext并不等于BeanFactory,毕竟是两个对象,并不是一个对象。尽管都复用了BeanFactory接口。
那真正的IoC的底层实现就是BeanFactory的实现类,因为ApplicationContext是委托DefaultListableBeanFactory来操作getBean等方法的。
(3)DefaultListableBeanFactory的设置
UserRepository中的BeanFactory beanFactory属性为什么通过autowired=“byType”,注入的是DefaultListableBeanFactory,而不是ClassPathXmlApplicationContext?既然他们两者属于BeanFactory接口,按type注入,为什么不是ClassPathXmlApplicationContext?
答案 在 org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory 方法中
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)
参数ConfigurableListableBeanFactory beanFactory来源于:obtainFreshBeanFactory()
还是组合进来的BeanFactory。
那么在方法体中,在解析内建依赖的时候:
代码
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
明确指定了,BeanFactory 类型的对象是 ApplicationContext#getBeanFactory() 方法的内容,而非它自身。