Spring 扩展点的执行顺序

2023-11-17 16:50:32 浏览数 (1)

1、Spring 扩展点的执行顺序

1.1、Spring 扩展点

1.1.1、BeanFactoryPostProcessor

Bean 工厂后置处理器,主要用于加载 Spring 中的 BeanDefinition。

方法

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

可以使用 beanFactory 进行 Bean 的 BeanDefinition 定义与修改。

Spring 中元素加载情况: 项目中所有的 BeanDefinition 已被加载,但是普通 Bean 还未被实例化和初始化。

禁止事项

1、禁止过早初始化 Bean,初始化后 BeanPostProcessor 的实现类将不能处理当前 Bean,比如最常见的动态代理后置处理器,也就是说当前的 Bean 会代理失效。举个粟子,不能这样->

代码语言:java复制
public class TestBean {
}

@Component
public class TestPostProcess implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.registerSingleton("testBean",new TestBean());
    }
}

当然,如果你就是不需要被 BeanPostProcessor 处理,这个可以不用理会。

2、禁止使用依赖注入,因为当前普通 Bean 还未被创建,对象不会注入,调用的值将会是 null。 

代码语言:less复制
@Component
public class TestBean {
}

@Component
public class TestPostProcess implements BeanFactoryPostProcessor {

    @Autowired
    private TestBean testBean;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//        这里将会输出 null
        System.out.println(testBean);
    }
}

实现类调用处: org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)

1.1.2、BeanDefinitionRegistryPostProcessor

继承于 BeanFactoryPostProcessor 类,新增 postProcessBeanDefinitionRegistry 方法。

新增方法

void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

扫描添加项目中的 BeanDefinition。

Spring 中元素加载情况: 项目中所有的 BeanDefinition 已被加载,但是普通 Bean 还未被实例化和初始化。

禁止事项

1、禁止使用 BeanDefinitionRegistryPostProcessor 的实现类注册 BeanDefinitionRegistryPostProcessor 实现类,这样被注册的 BeanDefinitionRegistryPostProcessor【postProcessBeanDefinitionRegistry】方法将不会执行。比如不能这样 ->

代码语言:java复制
@Component
public class TestBean1DefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor , PriorityOrdered {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    }
    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.registerSingleton("testBeanDefinitionRegistryPostProcessor",new TestBeanDefinitionRegistryPostProcessor());
    }

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

public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("我不会执行");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
}

实现类调用处: org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)

使用技巧

代码语言:java复制
@Component
public class TestBean1DefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor , PriorityOrdered {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        registry.registerBeanDefinition("testBean",new RootBeanDefinition(TestBean.class));
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        beanFactory.registerSingleton("testBeanDefinitionRegistryPostProcessor",new TestBeanDefinitionRegistryPostProcessor());
    }

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

1.1.3、BeanPostProcessor

Bean 的后置处理器,常用与对 Bean 的一些加工处理,比如最常见的动态代理。

方法

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

可以对 Bean 进行处理,比如替换等操作。

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

可以对 Bean 进行处理,比如替换等操作。

Spring 中元素加载情况: 项目中所有的 Bean 已创建,Bean 的属性已被自动装配。初始化方法还未被调用。

禁止事项

1、注意使用 registerBeanDefinition 注册 Bean,使用 registerBeanDefinition 注册 Bean 后,Bean 的初始化方法将会在 Bean 实际调用时执行。例如依赖注入,在依赖注入的地方会走 doGetBean 进而去进行实例创建和初始化。

代码语言:typescript复制
@Component
public class TestBean {

    @Autowired
    private TestBean1 testBean1;

    @PostConstruct
    public void init(){
        System.out.println(666);
        System.out.println(testBean1);
    }
}


public class TestBean1 {

    @PostConstruct
    public void init(){
        System.out.println(333);
    }

}


@Component
public class TestPostProcessor implements BeanPostProcessor {

    @Autowired
    private BeanFactory beanFactory;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) this.beanFactory;
        String registerBeanName = "testBean1";
        if (!beanDefinitionRegistry.containsBeanDefinition(registerBeanName)) {
            beanDefinitionRegistry.registerBeanDefinition(registerBeanName, new RootBeanDefinition(TestBean1.class));
        }

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

2、禁止使用 registerSingleton 注册 Bean,否则 Bean 的初始化方法不会得到执行,同样后置处理器也不会处理当前 Bean。具体原因我会在依赖注入中分析。这里先得出结果:由于使用当前方法注册的 Bean 实例已经有了,所以不会走创建实例和依赖注入,所以也就不会走初始化方法了。

代码语言:typescript复制
@Component
public class TestPostProcessor implements BeanPostProcessor {

    @Autowired
    private BeanFactory beanFactory;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

        ConfigurableListableBeanFactory beanDefinitionRegistry = (ConfigurableListableBeanFactory) this.beanFactory;
        String registerBeanName = "testBean1";
        if (!beanDefinitionRegistry.containsBean(registerBeanName)) {
            beanDefinitionRegistry.registerSingleton(registerBeanName, new TestBean1());
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

3、禁止使用依赖注入普通 Bean,这样会导致 Bean 提前初始化而让后置处理器不再处理当前 Bean。

代码语言:typescript复制
@Component
public class TestPostProcessor implements BeanPostProcessor {

    @Autowired
    private TestBean1 testBean1;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

或者

代码语言:typescript复制
@Configuration
public class TestConfig {

    @Bean
    public TestPostProcessor testPostProcessor(TestBean1 testBean1){
        return new TestPostProcessor();
    }
}

最经典的反例就是 Shiro 框架中的这个配置:

代码语言:text复制
 @Bean
    public DefaultWebSecurityManager securityManager(ShiroRealm shiroRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(shiroRealm);

        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        return securityManager;
    }

@Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        Map<String, Filter> filters = shiroFilterFactoryBean.getFilters();
        shiroFilterFactoryBean.setFilters(filters);
        shiroFilterFactoryBean.setFilterChainDefinitionMap(new HashMap<>());
        return shiroFilterFactoryBean;
    }

如果在 ShiroRealm 中依赖注入了对象,那么相关的代理会全部失效,也就是事务回滚会失效,注意注意!

请在 BeanFactoryPostProcessor 中注册 Bean。如果实现想要使用那么可以考虑在需要注入的 Bean 上标注 @Lazy 注解。当然如果你不在意以上缺点的话请忽略这些禁止项。

实现类调用处: org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization与org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization

1.1.4、自定义的init方法

Bean 初始化方法。可以在 Bean 定义中指定初始化方法 @Bean(initMethod = "initMethod")

org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata#invokeInitMethods

Spring 中元素加载情况: 已经实例化和依赖注入,在 InitDestroyAnnotationBeanPostProcessor 中 postProcessBeforeInitialization 调用,其实现 PriorityOrdered,order = 2147483647 

1.1.5、@PostConstruct 注解标注的方法

Bean 初始化方法。

调用处:org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization

1.1.6、Aware

通过实现 Aware 的各种实现类可以获取 Spring 内部的一些资源,比如 BeanFactoryAware、EnvironmentAware。Spring 将会以回调的方式注入各种资源。

代码语言:java复制
@Component
public class TestBeanFactoryAware implements BeanFactoryAware {

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        beanFactory.getBean("testBean");
    }
}

1.1.7、SmartInitializingSingleton

所有 Bean 实例化、初始化、并被所有后置处理器处理后的一个扩展点

方法

void afterSingletonsInstantiated();

实现类调用处: org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

1.2、扩展点执行顺序

BeanFactoryPostProcessor(内部的执行顺序请参考www.nblogs.cn/doc/spring/…)

====>

BeanPostProcessor 的 postProcessBeforeInitialization、BeanPostProcessor 的 postProcessAfterInitialization(其中初始化方法在他们里面执行)

====>

SmartInitializingSingleton的afterSingletonsInstantiated

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞