SpringIOC 的钩子

191 阅读6分钟

1 Aware接口

1.1 Aware 是什么

Aware 是一个空接口,方法签名交由其子接口实现,一般来说,其子接口只有一个setXXX 的方法

  1. ApplicationContextAware -> setApplicationContext
  2. BeanNameAware -> setBeanName

在前文中的spring 初始化中也有相关的代码

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        // BeanNameAware -> setBeanName
            if (bean instanceof BeanNameAware) {
                    ((BeanNameAware) bean).setBeanName(beanName);
            }
            // BeanClassLoaderAware -> setBeanClassLoader
            if (bean instanceof BeanClassLoaderAware) {
                    ClassLoader bcl = getBeanClassLoader();
                    if (bcl != null) {
                            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                    }
            }
            // BeanFactoryAware -> setBeanFactory
            if (bean instanceof BeanFactoryAware) {
                    ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
    }
}

1.2 子接口

其子接口何其多啊

image.png

我们举个简单的例子 BeanNameAware

package org.springframework.beans.factory;

public interface BeanNameAware extends Aware {
    void setBeanName(String var1);
}

1.3 演示


@Component
public class MyAwareTest implements BeanNameAware, BeanClassLoaderAware {
    String beanName;

    ClassLoader beanClassLoader;

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("调用了 MyAwareTest 的 setBeanClassLoader");
        this.beanClassLoader = beanClassLoader;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("调用了 MyAwareTest 的 setBeanName");
        beanName = beanName;
    }
}
@SpringBootApplication
public class CustomerServiceApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext cx = (ConfigurableApplicationContext) SpringApplication.run(CustomerServiceApplication.class, args);
        MyAwareTest beanTest = (MyAwareTest) cx.getBean("myAwareTest");

    }

输出结果为

调用了 MyAwareTest 的 setBeanName
调用了 MyAwareTest 的 setBeanClassLoader

2BeanPostProcessor接口

作用:在bean完成实例化后对其进行增强和配置

2.1 使用示例

@Component
public class BeanPostProcessorTest  implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bean " + beanName + " 调用了 postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bean " + beanName + " 调用了 postProcessAfterInitialization");
        return bean;    }
}
@SpringBootApplication
public class CustomerServiceApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext cx = (ConfigurableApplicationContext) SpringApplication.run(CustomerServiceApplication.class, args);
        BeanPostProcessorTest beanTest = (BeanPostProcessorTest) cx.getBean("beanPostProcessorTest");

    }
}

打印日志

bean connManFactory 调用了 postProcessBeforeInitialization
bean connManFactory 调用了 postProcessAfterInitialization
bean apacheHttpClientFactory 调用了 postProcessBeforeInitialization
bean apacheHttpClientFactory 调用了 postProcessAfterInitialization
bean org.springframework.cloud.commons.httpclient.HttpClientConfiguration 调用了 postProcessBeforeInitialization
bean org.springframework.cloud.commons.httpclient.HttpClientConfiguration 调用了 postProcessAfterInitialization

代码植入点

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
            // Make sure bean class is actually resolved at this point.
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                    Class<?> targetType = determineTargetType(beanName, mbd);
                    if (targetType != null) {
                            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                            if (bean != null) {
                                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                            }
                    }
            }
            mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                    if (result != null) {
                            return result;
                    }
            }
    }
    return null;
}

看到这里胖友们是不是觉得很简单,那如果我们换一个代码,还会出现一样的日志吗?

ClassPathResource resource = new ClassPathResource("spring.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);

BeanPostProcessorTest test = (BeanPostProcessorTest) factory.getBean("beanPostProcessorTest");

答案是否定的,因为普通的 BeanFactory 是不会实现 BeanPostProcessor的字段注册的

  • factory.addBeanPostProcessor(beanPostProcessorTest); 这种方法进行注册,
  • ApplicationContext 可以在其 bean 定义中自动检测所有的 BeanPostProcessor 并自动完成注册,同时将他们应用到随后创建的任何 Bean 中

2.2 原理

BeanPostProcessor 接口源码

public interface BeanPostProcessor {

	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

BeanPostProcessor 可以理解为Spring钩子(Aware 也是),开发人员可以在对象实例化的时候进行扩展,流程图如下

image.png

2.2.1 bean实例化中的源码

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}

try {
        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);
}

2.2.2 源码applyBeanPostProcessorsBeforeInitialization 源码

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
    Object result = existingBean;
    //遍历 beanPostProcessors
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            // 处理
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                    return result;
            }
    }
    return result;
}

2.2.3 源码applyBeanPostProcessorsAfterInitialization 源码

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessAfterInitialization(result, beanName);
            if (result == null) {
                    return result;
            }
    }
    return result;
}

2.3 ApplicationContext 如何实现自动注册

getBeanPostProcessors()返回的是所有 BeanPostProcessor 的集合,ApplicationContext之所以能够实现自动注册,是因为Spring在构造ApplicationContext 对象的时候会自动调用registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) ,将检测到的所有BeanPostProcessor 注入进去

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

public static void registerBeanPostProcessors(
		ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

    // 获取所有的 BeanPostProcessor 的 beanName(已经加载到容器中,但未实例化)
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    // 记录所有的beanProcessor数量
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    // 注册 BeanPostProcessorChecker,它主要是用于在 BeanPostProcessor 实例化期间记录日志
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    // 使用 Ordered 保证顺序
    List<String> orderedPostProcessorNames = new ArrayList<>();
    // 没有顺序
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        // PriorityOrdered
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 调用 getBean 获取 bean 实例对象
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 有序 Ordered
            orderedPostProcessorNames.add(ppName);
        } else {
            // 无序
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
    // 第一步,注册所有实现了 PriorityOrdered 的 BeanPostProcessor
    // 先排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 后注册
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
    // 第二步,注册所有实现了 Ordered 的 BeanPostProcessor
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
            }
    }
    // 先排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 后注册
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // 第三步注册所有无序的 BeanPostProcessor
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
            }
    }
    // 注册,无需排序
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 最后,注册所有的 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    
    // 加入ApplicationListenerDetector(探测器)
    // 重新注册 BeanPostProcessor 以检测内部 bean,因为 ApplicationListeners 将其移动到处理器链的末尾
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

sortPostProcessors 方法

PostProcessorRegistrationDelegate.sortPostProcessors
private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    // 获得 Comparator 对象
    Comparator<Object> comparatorToUse = null;
    if (beanFactory instanceof DefaultListableBeanFactory) { // 依赖的 Comparator 对象
        comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
    }
    if (comparatorToUse == null) { // 默认 Comparator 对象
        comparatorToUse = OrderComparator.INSTANCE;
    }
    // 排序
    postProcessors.sort(comparatorToUse);
}

registerBeanPostProcessors 方法

private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    // 遍历 BeanPostProcessor 数组,注册
    for (BeanPostProcessor postProcessor : postProcessors) {
            beanFactory.addBeanPostProcessor(postProcessor);
    }
}
  • BeanPostProcessor 是容器级别
  • ApplicationContext 可以实现BeanPostProcessor的自动注册,BeanFactory 需要手动调用AbstractBeanFactory.addBeanPostProcessor
  • ApplicationContext 可以实现BeanPostProcessor 的自定排序,BeanFactory只和注册顺序有关

3InitializingBeaninit-method

InitializingBean 接口为bean 提供了初始化功能,具体源码如下

public interface InitializingBean {

    /**
     * 该方法在 BeanFactory 设置完了所有属性之后被调用,允许 bean 实例设置了所有 bean 属性时执行初始化工作,如果该过程出现了错误则需要抛出异常
     */
    void afterPropertiesSet() throws Exception;

}

3.1 案例

@Component
@Data
public class InitializingBeanTest implements InitializingBean {

    String beanName;
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用 InitializingBeanTest 的方法 afterPropertiesSet" );
        this.beanName ="naonao";
    }

    public String getBeanName() {
        return beanName;
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
}

@SpringBootApplication
public class CustomerServiceApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext cx = (ConfigurableApplicationContext) SpringApplication.run(CustomerServiceApplication.class, args);
        InitializingBeanTest beanTest = (InitializingBeanTest) cx.getBean("initializingBeanTest");
        System.out.println(beanTest.getBeanName());;
    }
}

输出

beanName is naonao

示例中改变了beanName的名字,那么究竟是在哪里做的改动呢?答案是AbstractAutowireCapableBeanFactory.invokeInitMethods``

3.2 方法 invokeInitMethods

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
    // 首先会检查是否是 InitializingBean ,如果是的话需要调用 afterPropertiesSet()
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            //日志代码
        }
        if (System.getSecurityManager() != null) { // 安全模式
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    // 属性初始化的处理
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            } catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        } else {
            // 属性初始化的处理
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null && bean.getClass() != NullBean.class) {
        // 判断是否指定了 init-method(),
        // 如果指定了 init-method(),则再调用制定的init-method
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 激活用户自定义的初始化方法
            // 利用反射机制执行
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}
  1. 检测当前 bean 是否实现了 InitializingBean 接口,如果实现了则调用其afterPropertiesSet()方法。
  2. 检查是否也指定了 init-method如果指定了则通过反射机制调用指定的 init-method 方法。

3.3 方法init-method

init-method 的作用和InitializingBean 作用一致,只不过是配置在 xml文件里,这里就不多做赘述了

3.4 销毁

与之对应的还有DisposableBeandestroy-method

4 容器扩展机制 BeanFactoryPostProcessor

BeanFactoryPostProcessor 是一种容器扩展机制,作用于容器启动阶段,可以让开发者在容器对bean实例化之前对注册到容器的BeanDefinition进行更改 源码如下

public interface BeanFactoryPostProcessor {
 /**
  *1、Modify the application context's internal bean factory after its standard initialization.
  *
  * 2、All bean definitions will have been loaded, but no beans will have been instantiated yet. This allows for overriding or adding properties even to eager-initializing beans
 */
 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
  • postProcessBeanFactory()的作用:在BeanDefinition 完成加载之后,Bean 实例化之前 对加载 BeanDefinition 进行修改。 BeanFactoryPostProcessor 操作的是BeanDefinitionBeanPostProcessor 操作的是bean,2者有着本质的不同,千万不能混为一谈。而且BeanFactoryPostProcessor 也支持排序

4.1 案例

@Component
public class BeanFactoryPostProcessorTest implements BeanFactoryPostProcessor, Ordered {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("调用 BeanFactoryPostProcessorTest postProcessBeanFactory");
        System.out.println("容器中的个数  " + beanFactory.getBeanDefinitionCount());

        BeanDefinition bd = beanFactory.getBeanDefinition("myAwareTest");
        MutablePropertyValues propertyValues = bd.getPropertyValues();
        propertyValues.add("beanName", "王小闹");
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

@Component
public class BeanFactoryPostProcessorTes2 implements BeanFactoryPostProcessor, Ordered {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("调用 BeanFactoryPostProcessorTest postProcessBeanFactory");
        System.out.println("容器中的个数  " + beanFactory.getBeanDefinitionCount());

        BeanDefinition bd = beanFactory.getBeanDefinition("myAwareTest");
        MutablePropertyValues propertyValues = bd.getPropertyValues();
        propertyValues.add("beanName", "王小闹2");
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

@SpringBootApplication
public class CustomerServiceApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext cx = (ConfigurableApplicationContext) SpringApplication.run(CustomerServiceApplication.class, args);
        MyAwareTest beanTest = (MyAwareTest) cx.getBean("myAwareTest");
        System.out.println("beanName is " +beanTest.getBeanName());;
    }
}

4.2 小结

BeanFactoryPostProcessorBeanPostProcessor 一样,会被ApplicationContext 自动识别并注册,但是BeanFactory 要手动注册

5