前面分析了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
@Component
public class ComponentAImple implements Component {
private String mark = "a";
}
@Component
public class ComponentBImple implements Component {
private String mark = "b";
}
创建一个junit单元测试类
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = SpringTest2Config.class)
public class TestSpring1 {
@Autowired
private Component component;
@Test
public void test(){
}
}
注入一个 component类型的对象。上面这个程序启动肯定是会报错的
原因:因为Component类型的对象有两个,而且都是由Spring管理的,Spring注入对象的时候发现了多个,它不知道应该注入哪个对象而抛出异常
可以使用 @Primary 注解,但是这个注解不在这里讨论
我们可以使用 registerResolvableDependency()
方法来实现。创建一个 TestRegisterResolvableDependency
类,实现BeanFactoryPostProcessor
接口 并放到IOC容器中
@Component
public class TestRegisterResolvableDependency implements BeanFactoryPostProcessor {
@Override
public 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上下文中。
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 当上下文不为空时且该bean是ApplicationListener
if (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 fly
this.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 events
logger.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上下文中。