在refresh方法的invokeBeanFactoryPostProcessors方法中,后置处理器的执行流程
1、首先调用context传入的BeanDefinitionRegistryPostProcessor接口
2、调用Spring注入的BeanDefinitionRegistryPostProcessor接口(ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry => 包扫描,Import等)会添加到已执行的集合中
3、调用扫描出来的BeanDefinitionRegistryPostProcessor接口实现类(分三个级别调用)会添加到已执行的集合中
4、调用所有的BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法
5、调用context.add手动注入的BeanFactoryPostProcessor接口的postProcessBeanFactory方法(不会添加到已执行集合中)
6、最终获取容器中所有的BeanFactoryPostProcessor接口的实现类,逐一检查是否回调过,没有回调的根据优先级回调(context添加的BeanFactoryPostProcessor、spring扫描的BeanFactoryPostProcessor)
使用context.addBeanFactoryPostProcessor添加到的BeanFactoryPostProcessor接口的实现类会被执行两次
前面记录了ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry方法,接下来就会执行ConfigurationClassPostProcessor#postProcessBeanFactory方法
Spring注入的类中
ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor
EventListenerMethodProcessor 实现了 BeanFactoryPostProcessor
AutowiredAnnotationBeanPostProcessor 实现了BeanPostProcessor
CommonAnnotationBeanPostProcessor 实现了BeanPostProcessor
接下来主要分析ConfigurationClassPostProcessor#postProcessBeanFactory和EventListenerMethodProcessor#postProcessBeanFactory
InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置。AbstractAutowireCapableBeanFactory#createBean方法的Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
方法里面执行了这个后置处理器
/* 在目标对象实例化之前调用,方法的返回值类型是Object,我们可以返回任何类型的值。
* 由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(一般都是代理对象)。
* 如果该方法的返回值代替原本该生成的目标对象,
* 后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
*/
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
/* 方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。
* 如果该方法返回false,会忽略属性值的设置;
* 如果返回true,会按照正常流程设置属性值。
* 方法不管postProcessBeforeInstantiation方法的返回值是什么都会执行
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
// 在spring的工厂属性注入之前,自己指定属性的值
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
}
// 方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法不会被调用。可以在该方法内对属性值进行修改
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
还有父接口BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法都是在目标对象被实例化之后,并且属性也被设置之后调用的
SmartInstantiationAwareBeanPostProcessor
智能实例化Bean后置处理器(继承InstantiationAwareBeanPostProcessor)
// 预测bean的类型
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
// 检测Bean的构造器,可以检测出多个候选构造器
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
// 循环引用的后置处理器,获得提前暴露的bean引用。主要用于解决循环引用的问题,只有单例对象才会调用此方法
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
MergedBeanDefinitionPostProcessor
// 在bean初始化之前合并一些东西到bd中 比如:bean的初始化回调和销毁回调方法
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
// 重置 BeanDefinition 缓存
default void resetBeanDefinition(String beanName) {}
ConfigurationClassPostProcessor
ConfigurationClassPostProcessor#postProcessBeanFactory这个方法的作用是通过用cglib增强配置类,准备在运行时为bean请求提供服务。也就是在Configuration注解类的 方法中调用 @Bean修饰的方法时,为了保证每一个bean都是单例,会首先去容器搜索@Bean修饰的这个对象是否在容器中存在,如果存在就直接返回容器中的对象,不存在就会调用@Bean对应的方法逻辑构建一个bean对象放入容器中并返回这个对象。以上这种机制是通过cglib代理中的拦截器实现的。
// ConfigurationClassPostProcessor
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// cglib 代理 ConfigurationClass
enhanceConfigurationClasses(beanFactory);
// 注册了 ImportAwareBeanPostProcessor bean的后置处理器(这个后置处理器非常重要)
// postProcessProperties方法主要是为 EnhancedConfiguration 类注入一个beanFactory
// postProcessBeforeInitialization 方法为 ImportAware 类型的bean注入一个 AnnotationMetadata
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
// ConfigurationClassPostProcessor
// 这个方法会找到bdMap中的所有配置类,任何一个配置类都会被 ConfigurationClassEnhancer 代替
// 区别的方式就是 full 和 lite
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
// 循环 bdMap
for (String beanName : beanFactory.getBeanDefinitionNames()) {
BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
// full
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
}
}
// 没有配置类去代理 直接返回
if (configBeanDefs.isEmpty()) return;
// 有配置类需要去一一代理,替换原bd中的class
for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
AbstractBeanDefinition beanDef = entry.getValue();
// If a @Configuration class gets proxied, always proxy the target class 设置标识
beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
// 为代理类配置他需要代理的类,使用同一个类加载器
Class<?> configClass = beanDef.resolveBeanClass(this.beanClassLoader);
if (configClass != null) {
// 生成代理对象
Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
if (configClass != enhancedClass) {
// 把bd中的beanClass替换为代理对象
beanDef.setBeanClass(enhancedClass);
}
}
}
}
创建代理对象的逻辑
// ConfigurationClassEnhancer#enhance
// configClass 这个参数是需要代理的class
// classLoader 加载这个configClass的classLoader
public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
// 创建代理
Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
return enhancedClass;
}
// 创建一个新的cglib对象实例
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(configSuperClass);
// 设置这个接口是为了注入一个属性 $$beanFactory 注入了beanFactory之后,就可以通过beanFactory去容器中获取对象
// 这个接口继承了 BeanFactoryAware 接口,这个aware接口可以拿到beanFactory对象
// 检查方法返回值的对象是否已经在容器中存在了
enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
enhancer.setUseFactory(false);
// 生成名称策略
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
// 注册一些方法拦截器 => 方法指的时每一个入栈的方法 => 在a方法中调用了b c方法,则这里需要拦截三次,每一个方法都会拦截
enhancer.setCallbackFilter(CALLBACK_FILTER);
enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
return enhancer;
}
private Class<?> createClass(Enhancer enhancer) {
Class<?> subclass = enhancer.createClass();
// subclass 就是我们创建的代理对象
// 这里就是为这个代理对象的静态方法注入这些方法拦截器(CALLBACKS)
Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
return subclass;
}
// 默认的前置处理
private static final Callback[] CALLBACKS = new Callback[] {
new BeanMethodInterceptor(),
new BeanFactoryAwareMethodInterceptor(),
NoOp.INSTANCE
};
生成的代理对象如下所示:
public class AppConfig$$EnhancerBySpringCGLIB$$af448cfe extends AppConfig implements EnhancedConfiguration {
public BeanFactory $$beanFactory;
// 注入BeanFactory
public final void setBeanFactory(BeanFactory var1) throws BeansException {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_1;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_1;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$setBeanFactory$6$Method, new Object[]{var1}, CGLIB$setBeanFactory$6$Proxy);
} else {
super.setBeanFactory(var1);
}
}
// 对@Bean方法的代理
public final UserTest2 userTest2() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
// 如果存在方法拦截器,返回拦截器的intercept方法返回的值
return var10000 != null ? (UserTest2)var10000.intercept(this, CGLIB$userTest2$1$Method, CGLIB$emptyArgs, CGLIB$userTest2$1$Proxy) : super.userTest2();
}
}
拦截器
拦截器会拦截代理对象中的所有方法
1、BeanFactoryAwareMethodInterceptor
BeanFactoryAwareMethodInterceptor这个拦截器就是为代理对象中注入BeanFactory对象
// obj代理对象
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 获取 BEAN_FACTORY_FIELD = $$beanFactory 字段
Field field = ReflectionUtils.findField(obj.getClass(), BEAN_FACTORY_FIELD);
// 设置 $$beanFactory属性的值
field.set(obj, args[0]);
// Does the actual (non-CGLIB) superclass implement BeanFactoryAware?
// If so, call its setBeanFactory() method. If not, just exit.
if (BeanFactoryAware.class.isAssignableFrom(ClassUtils.getUserClass(obj.getClass().getSuperclass()))) {
return proxy.invokeSuper(obj, args);
}
return null;
}
可以看出设置的值是args[0],这里beanFactory的注入是ImportAwareBeanPostProcessor这个后置处理器在对象创建时将beanFactory对象传进来了。
// ImportAwareBeanPostProcessor#postProcessProperties
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
if (bean instanceof EnhancedConfiguration) {
// 调用set方法的时候会被cglib代理中的拦截器拦截
((EnhancedConfiguration) bean).setBeanFactory(this.beanFactory);
}
return pvs;
}
2、BeanMethodInterceptor @Bean方法的拦截器
核心方法intercept
// ConfigurationClassEnhancer.BeanMethodInterceptor
// 代理一个方法,在方法执行之前,检查容器是否存在方法返回的对象
// enhancedConfigInstance 代理对象
// beanMethod 配置类的方法
// beanMethodArgs 方法参数
// cglibMethodProxy 代理方法
public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,MethodProxy cglibMethodProxy) throws Throwable {
// 通过反射代理对象得到代理对象中的 beanFactory 对象
ConfigurableBeanFactory beanFactory = getBeanFactory(enhancedConfigInstance);
String beanName = BeanAnnotationHelper.determineBeanNameFor(beanMethod);
/*
首先,检查请求的bean是否是 FactoryBean。如果是这样,创建一个子类代理,拦截对getObject()的调用并返回任何缓存的bean实例。
这确保了从 @Bean 方法中调用FactoryBean的语义与在XML中引用FactoryBean的语义相同
检查 这个 &beanName 这个beanName在容器中是否存在对应的bd或者bean对象
如果存在,则说明这个 beanName 是一个 factoryBean ,则不能返回它构造函数生成的对象
那么我们需要返回这个类(beanName)的 getObject 方法返回的对象,所以需要对 beanName 这个类进行代理,返回 getObject 方法返回的对象
同时在getObject方法调用的时候,spring 先去从容器获取 beanName 对应的bd或者bean 如果存在就不会执行getObject方法,直接返回从容器中获取的对象
*/
if (factoryContainsBean(beanFactory, BeanFactory.FACTORY_BEAN_PREFIX + beanName) &&
factoryContainsBean(beanFactory, beanName)) {
Object factoryBean = beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
if (factoryBean instanceof ScopedProxyFactoryBean) {
// 存在作用域的 FactoryBean 这里不需要处理这种
}else {
// 返回 factoryBean 的代理对象 => 对getObject方法进行拦截
return enhanceFactoryBean(factoryBean, beanMethod.getReturnType(), beanFactory, beanName);
}
}
/**
* isCurrentlyInvokedFactoryMethod 这个判断是决定是执行方法还是从荣容器中获取对象的关键判断
* 前面说过,每调用一个方法都会被拦截,那么怎么判断调用的方法是不是以及被调用过了呢?
* 也就是怎么确定这个方法是第一次调用,因为第一次调用需要执行方法中的方法体来创建对象
* beanMethod 指的到当前调用的方法,比如在 a 方法中调用了 b 和 c 方法
* 如果这拦截器拦截了a方法,那么这个beanMethod就是a方法,同理,拦截了b ,beanMethod就是b方法
* 解决方法:维护了一个ThreadLocal的变量,在方法第一调用时,会将这个方法放入的变量中
* 比如 先调用了a方法,那么调用b方法的时候,就会去比较 a 和 b 方法,发现方法不一致
* 那么就会去容器找这个beanName 对应的bean对象,如果存在这个bean对象,就直接返回这个bean对象,没有就回去创建这个bean对象,并将它放入容器
* 如果调用的是当前方法,那么就直接调用父类(真正的配置类对象)的方法
*/
if (isCurrentlyInvokedFactoryMethod(beanMethod)) {
// create the bean instance.
// 当前执行的方法和调用的方法是同一个方法,直接调用父类的方法进行对象的创建,并返回
return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
}
// 不是同一个方法,就调用 $$beanFactory 去容器中获取对应的对象
return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
}
对FactoryBean对象的代理
private Object enhanceFactoryBean(final Object factoryBean, Class<?> exposedType,
final ConfigurableBeanFactory beanFactory, final String beanName) {
Class<?> clazz = factoryBean.getClass();
boolean finalClass = Modifier.isFinal(clazz.getModifiers());
boolean finalMethod = Modifier.isFinal(clazz.getMethod("getObject").getModifiers());
if (finalClass || finalMethod) {
// final方法或者final类 尝试使用JDK的动态代理
if (exposedType.isInterface()) {
// 存在接口,通过接口使用jdk的动态代理,返回代理对象
// 在代理对象会对 getObject 方法进行拦截,从容器中找这个beanName,如果存在就返回
// 不存在就执行目标方法进行创建,beanName 不带有 & 符号的
return createInterfaceProxyForFactoryBean(factoryBean, exposedType, beanFactory, beanName);
}else{
// final类型的没有接口就不能代理
// 直接返回这个 factoryBean 对象(从容器中通过 &beanName 获取的对象)
return factoryBean;
}
}
// 返回cglib代理的对象 同样时拦截 getObject 方法,添加了一个处理器
// 和使用jdk代理相同的逻辑,
return createCglibProxyForFactoryBean(factoryBean, beanFactory, beanName);
}
JDK的动态代理
private Object createInterfaceProxyForFactoryBean(final Object factoryBean, Class<?> interfaceType,final ConfigurableBeanFactory beanFactory, final String beanName) {
return Proxy.newProxyInstance(
factoryBean.getClass().getClassLoader(), new Class<?>[] {interfaceType},
(proxy, method, args) -> {
if (method.getName().equals("getObject") && args == null) {
// 直接从容器中获取真正的对象
return beanFactory.getBean(beanName);
}
return ReflectionUtils.invokeMethod(method, factoryBean, args);
});
}
CGLib代理
private Object createCglibProxyForFactoryBean(final Object factoryBean,final ConfigurableBeanFactory beanFactory, final String beanName) {
// 同样时拦截 getObject 方法
((Factory) fbProxy).setCallback(0, (MethodInterceptor) (obj, method, args, proxy) -> {
if (method.getName().equals("getObject") && args.length == 0) {
return beanFactory.getBean(beanName);
}
return proxy.invoke(factoryBean, args);
});
return fbProxy;
}
EventListenerMethodProcessor
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
List<EventListenerFactory> factories = new ArrayList<>(beans.values());
AnnotationAwareOrderComparator.sort(factories);
this.eventListenerFactories = factories;
}
获取容器中所有的EventListenerFactory,并缓存在eventListenerFactories集合中。这里与Spring的事件监听机制有关,后续补充...