目录
ApplicationContextAwareProcessor处理器继承自BeanPostProcessor,主要是对spring中实现自Aware接口的EnvironmentAware、ApplicationContextAware等进行后置处理,ignoredDependencyInterfaces主要是缓存需要在bean进行属性注入时需要忽略的接口
1 ApplicationContextAwareProcessor
1.1 注册时机
该后置处理器主要是在prepareBeanFactory
中注册的
...
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
//添加该后置处理器到beanPostProcessors中
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartup.class);
...
1.2 调用时机
调用时机同BeanPostProcessor
,在bean初始化前后调用
...
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//调用是BeanNameAware、BeanClassLoaderAware和BeanFactoryAware的bean的处理器,实现名字、类加载器和工厂的设置(通过setXX)
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行初始化前操作postProcessBeforeInitialization,ApplicationContextAwareProcessor就是在这里调用
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//执行bean初始化,如果有的话
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//初始化后操作
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
...
1.3 执行逻辑
主要是针对实现了指定几个Aware接口的类进行统一的属性设置
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//具体的几个实现Aware接口的接口,这几个接口只有对应的setXX函数
if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware) && !(bean instanceof ApplicationStartupAware)) {
return bean;
} else {
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareInterfaces(bean);
return null;
}, acc);
} else {
//执行设置操作
this.invokeAwareInterfaces(bean);
}
return bean;
}
}
设置操作如下
...
if (bean instanceof MessageSourceAware) {
((MessageSourceAware)bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationStartupAware) {
((ApplicationStartupAware)bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
}
//执行对应类的setXX函数实现对应的属性设置
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
...
上述使用ApplicationContextAwareProcessor
的实现了这几个特定的容器属性设置,而没有在populateBean
中注入,主要是在我们prepareBeanFactory
时使用了 ignoredDependencyInterfaces
2 ignoredDependencyInterfaces
2.1 作用
该缓存主要作用时忽略实现了如ApplicationContextAware
接口中的setXX自动注入
public interface ApplicationContextAware extends Aware {
//实现此接口的类在自动注入时会忽略setApplicationContext的注入也即使忽略对应参数ApplicationContext的注入
void setApplicationContext(ApplicationContext var1) throws BeansException;
}
上述忽略之后就是由ApplicationContextAwareProcessor
来实现属性感知的,应该是要确保bean对应注入的上下文,环境等确保是生成该bean的容器
2.2 添加时机
与ApplicationContextAwareProcessor
添加时机同都在prepareBeanFactory
中
... beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.ignoreDependencyInterface(ApplicationStartup.class);
...
将对应的几个需要忽略的接口添加到缓存ignoredDependencyInterfaces
中,后续进行属性填充时根据此缓存进行过滤
2.3 判断时机
在populateBean
时进行判断
//存在后置处理器:一个实例化后但在设置显式属性或自动装配发生之前的回调
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
//进行依赖属性检测,会对ignoredDependencyInterfaces和ignoredDependencyTypes进行过滤
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
//需要依赖检测,也会进行判断
if (needsDepCheck) {
if (filteredPds == null) {
//过滤属性
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
filterPropertyDescriptorsForDependencyCheck
核心流程(从给定的BeanWrapper中提取一组经过筛选的属性描述符,*排除被忽略的依赖类型或属性定义在被忽略的依赖接口上):
PropertyDescriptor[] filtered = this.filteredPropertyDescriptorsCache.get(bw.getWrappedClass());
//如果之前已经存在缓存,不进行判断
if (filtered == null) {
//判断逻辑
filtered = filterPropertyDescriptorsForDependencyCheck(bw);
//是否需要缓存
if (cache) {
PropertyDescriptor[] existing =
this.filteredPropertyDescriptorsCache.putIfAbsent(bw.getWrappedClass(), filtered);
if (existing != null) {
filtered = existing;
}
}
}
return filtered;
属性过滤判断,返回过滤后的类属性数组
protected PropertyDescriptor[] filterPropertyDescriptorsForDependencyCheck(BeanWrapper bw) {
//获取beanwrapper的属性数组
List<PropertyDescriptor> pds = new ArrayList<>(Arrays.asList(bw.getPropertyDescriptors()));
//进行判断过滤
pds.removeIf(this::isExcludedFromDependencyCheck);
return pds.toArray(new PropertyDescriptor[0]);
}
isExcludedFromDependencyCheck
这是java8中的语法糖,提高代码间接性,作为函数参数,这样用需要一个函数式接口来接收使用。
protected boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
//主要判断逻辑
return (AutowireUtils.isExcludedFromDependencyCheck(pd) ||
this.ignoredDependencyTypes.contains(pd.getPropertyType()) ||
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces));
}
isExcludedFromDependencyCheck
判断
//排除CGLIB声明的属性
public static boolean isExcludedFromDependencyCheck(PropertyDescriptor pd) {
Method wm = pd.getWriteMethod();
if (wm == null) {
return false;
}
if (!wm.getDeclaringClass().getName().contains("$$")) {
// Not a CGLIB method so it's OK.
return false;
}
// It was declared by CGLIB, but we might still want to autowire it
// if it was actually declared by the superclass.
Class<?> superclass = wm.getDeclaringClass().getSuperclass();
return !ClassUtils.hasMethod(superclass, wm);
}
AutowireUtils.isSetterDefinedInInterface(pd, this.ignoredDependencyInterfaces)
判断缓存中是否包含该类型,有的话排除。
AutowireUtils.isSetterDefinedInInterface
判断
//返回给定bean属性的setter方法是否在任何给定接口中定义
public static boolean isSetterDefinedInInterface(PropertyDescriptor pd, Set<Class<?>> interfaces) {
Method setter = pd.getWriteMethod();
if (setter != null) {
Class<?> targetClass = setter.getDeclaringClass();
for (Class<?> ifc : interfaces) {
//判断逻辑目标类是否是ignoredDependencyInterfaces接口中的实现类,并且接口中定义了该setXX方法,满足需要进行排除
if (ifc.isAssignableFrom(targetClass) && ClassUtils.hasMethod(ifc, setter)) {
return true;
}
}
}
return false;
}
注意如果我们自定义了需要进行忽略的类,并不能忽略@Resource和@Autowired通过名字或者类型进行的注入,因为这两个在属性注入的时候是直接进行注入的不会考虑ignoredDependencyInterfaces,这个主要是针对在beans标签中使用default-autowire属性来注入依赖。
2.4 测试
定义A,C 和MyBeanFatoryPostProcessor
//A定义
public class A {
C c;
public C getC() {
return c;
}
public void setC(C c) {
this.c = c;
}
public void get(){
System.out.println(c);
}
}
//C定义
public class C {
private String name = "123";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//MyBeanFatoryPostProcessor定义
public class MyBeanFatoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
configurableListableBeanFactory.ignoreDependencyType(C.class);
}
}
测试类如下:
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:spring-1.xml");
A bean = classPathXmlApplicationContext.getBean(A.class);
bean.get();
其中spring-1.xml配置文件如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
default-autowire="byType">
<bean class="com.example.springboot1.ceshi.MyBeanFatoryPostProcessor"></bean>
<bean id="a" class="com.example.springboot1.ceshi.A"></bean>
<bean id="c" class="com.example.springboot1.ceshi.C"></bean>
</beans>
在我们注册了MyBeanFatoryPostProcess这个bean之后运行结果如下
当我们注释掉configurableListableBeanFactory.ignoreDependencyType(C.class)
运行如下
可以看出我们定义的MyBeanFatoryPostProcess添加了需要忽略的类型,所以后边注入属性的时候C为null,