前面分析了prepareBeanFactory的前面一段。主要的作用如下:
- 为工厂设置类的加载器、表达式解析器、属性编辑器注册器等
- 为工厂添加后处理器、要忽略的依赖接口
- 在工厂中注册可解析的依赖
- 在工厂中提前注册一些单例Bean
上一节的源码主要是分析了前面的两个;1:设置了PropertyEditorRegistrar,这个可以用来实现自定义数据类型的装换。2:设置了ApplicationContextAwareProcessor。这个接口主要是用来用户可以自己实现Aware接口,实现这个接口可以做到获取Spring内置的一些对象。接下来我们分析后面的一段:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// BeanFactory interface not registered as resolvable type in a plain factory.// MessageSource registered (and found for autowiring) as a bean.beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);beanFactory.registerResolvableDependency(ResourceLoader.class, this);beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);beanFactory.registerResolvableDependency(ApplicationContext.class, this);// Register early post-processor for detecting inner beans as ApplicationListeners.beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));// Detect a LoadTimeWeaver and prepare for weaving, if found.if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));// Set a temporary ClassLoader for type matching.beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}// Register default environment beans.if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());}if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());}if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());}}
一、beanFactory.registerResolvableDependency方法
registerResolvableDependency()方法是声明在 ConfigurableListableBeanFactory接口中的在初始化IOC中的时候,在AbstractApplicationContext#prepareBeanFactory中被调用。该方法的作用如下:
在Spring自动装配的时候如果一个接口有多个实现类,并且都已经放到IOC中去了,那么自动装配的时候就会出异常,因为spring不知道把哪个实现类注入进去,但是如果我们自定义一个类,然后实现BeanFactoryPostProcessor接口在该阶段调用这个方法,如果哪个地方要自动注入这个类型的对象的话,那么就注入进去我们指定的对象。
实战:定义 Component 接口
public interface Component {}
然后创建两个Component的实现类,分别为 ComponentAImple 和 ComponentBImlp
@Componentpublic class ComponentAImple implements Component {private String mark = "a";}@Componentpublic class ComponentBImple implements Component {private String mark = "b";}
创建一个junit单元测试类
@RunWith(SpringRunner.class)@ContextConfiguration(classes = SpringTest2Config.class)public class TestSpring1 {@Autowiredprivate Component component;@Testpublic void test(){}}
注入一个 component类型的对象。上面这个程序启动肯定是会报错的
原因:因为Component类型的对象有两个,而且都是由Spring管理的,Spring注入对象的时候发现了多个,它不知道应该注入哪个对象而抛出异常
可以使用 @Primary 注解,但是这个注解不在这里讨论
我们可以使用 registerResolvableDependency()方法来实现。创建一个 TestRegisterResolvableDependency 类,实现BeanFactoryPostProcessor接口 并放到IOC容器中
@Componentpublic class TestRegisterResolvableDependency implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {beanFactory.registerResolvableDependency(Component.class, new ComponentAImple());}}
注意beanFactory.registerResolvableDependency(Component.class, new ComponentAImple()); 方法,这行代码的意思是,当有其他类要注入 Component类型的对象时,就给他注入我们这里自己创建的 ComponentAImple对象。
可以参考文章:https://blog.csdn.net/yuge1123/article/details/106053857 这篇文章主要写的是
beanFactory.registerResolvableDependency()方法的用法。
二、ApplicationListenerDetector
ApplicationListenerDetector是Spring中内置的BeanPostProcessor实现,主要是为了检测Spring容器中的的ApplicaiontListener,然后将其注册到Spring上下文中。
@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) {// 当上下文不为空时且该bean是ApplicationListenerif (this.applicationContext != null && bean instanceof ApplicationListener) {// potentially not detected as a listener by getBeanNamesForType retrieval// 如果是单例,则将该bean注册至上下文中Boolean flag = this.singletonNames.get(beanName);if (Boolean.TRUE.equals(flag)) {// singleton bean (top-level or inner): register on the flythis.applicationContext.addApplicationListener((ApplicationListener<?>) bean);}else if (Boolean.FALSE.equals(flag)) {if (logger.isWarnEnabled() && !this.applicationContext.containsBean(beanName)) {// inner bean with other scope - can't reliably process eventslogger.warn("Inner bean '" + beanName + "' implements ApplicationListener interface " +"but is not reachable for event multicasting by its containing ApplicationContext " +"because it does not have singleton scope. Only top-level listener beans are allowed " +"to be of non-singleton scope.");}this.singletonNames.remove(beanName);}}return bean;}
ApplicationListenerDetector实现了实例化后进行后置处理的逻辑,主要就是检测ApplicationListener,然后将其加入Spring上下文中。
