美文网首页
spring动态注册bean会使AOP失效?

spring动态注册bean会使AOP失效?

作者: linyb极客之路 | 来源:发表于2022-04-12 10:06 被阅读0次

前言

本文的素材来自读者的一个问题,他看过我之前写的一篇博文聊聊如何把第三方服务注册到我们项目的spring容器中。刚好他项目中也有类似这样的一个需求,他就采用我文中介绍的第三种方法

调用beanFactory.registerSingleton()

一开始项目运行得还可以,后面他在这个第三方服务中使用AOP,发现AOP始终没有生效。于是他就给我留言了。今天就来聊一下这个话题,为什么使用registerSingleton()注册的bean,无法使AOP生效

问题根源

registerSingleton()这个方法直接将bean存放到单例池里面了。

如果对bean的生命周期有了解的朋友,应该会知道,bean可能会经过一系列的后置处理器后,再存放到单例池里面。因此这个bean可能是会被增强的,其中当然包括经过AOP增强

而使用registerSingleton()相当于是直接走捷径,不经过后置处理器,一步到位直接存放到单例池中。如果第三方服务是直接通过new出来的,就是一个普通的对象,因此注入到IOC容器后,也只是一个普通的bean,并没有任何增强

问题修复

方案一:不使用registerSingleton(),而是使用BeanDefinition注册方式

这种方式本质是让这个对象完整经历了bean的生命周期

示例:

@Configuration
public class HelloServiceConfiguration implements BeanFactoryPostProcessor {


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition();
        AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        beanDefinition.setBeanClass(HelloService.class);
        HelloServiceProperties properties = new HelloServiceProperties();
        properties.setBeanName("helloService");
        beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0,properties);
        defaultListableBeanFactory.registerBeanDefinition(properties.getBeanName(),beanDefinition);

    }
}

方案二、使用registerSingleton(),但注入的对象不是用new出来的,而是直接注入AOP代理对象

主要利用AOP的代理api:AnnotationAwareAspectJAutoProxyCreator

示例

@Configuration
public class HelloServiceWithProxyConfiguration implements BeanFactoryAware, InitializingBean {

    private BeanFactory beanFactory;

    @Autowired
    private AnnotationAwareAspectJAutoProxyCreator annotationAwareAspectJAutoProxyCreator;


    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void afterPropertiesSet() throws Exception {

        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory)beanFactory;
        HelloServiceProperties properties = new HelloServiceProperties();
        properties.setBeanName("helloService");
        HelloService helloServicePrxoy = (HelloService) annotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization(new HelloService(properties), "helloService$$Prxoy");
        defaultListableBeanFactory.registerSingleton(properties.getBeanName(),helloServicePrxoy);

    }
}

总结

以上两种方案,建议使用方案一。因为方案一完整经历过bean的生命周期,这就意味着可以获取spring提供的各种增强功能。方案二反而更像是硬编码进去,如果后面要使用spring的其他增强的功能,就还必须调用其他API。不过如果可以确定业务不会使用spring提供的各种扩展功能。方案二也是可以的

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-registerSingleton-aop-invalid

相关文章

  • spring动态注册bean会使AOP失效?

    前言 本文的素材来自读者的一个问题,他看过我之前写的一篇博文聊聊如何把第三方服务注册到我们项目的spring容器中...

  • aop

    使用: spring aop使用简单示例 开启单个bean的代理,ProxyFactoryBean aop失效 a...

  • Spring AOP的总体流程

    注册解析 AOP的服务 解析和加载横切逻辑 将横切逻辑织入目标Bean中 Spring 动态代理不会干预 Bean...

  • 180804-Spring之动态注册bean

    Spring之动态注册bean 什么场景下,需要主动向Spring容器注册bean呢? 如我之前做个的一个支持扫表...

  • Spring动态注入Bean

    动态注册bean的两种api Spring中的bean定义都保存在 BeanDefinitionRegistry ...

  • Aop 源码解读

    动态Aop的使用 创建用于拦截的bean 创建 Advisor spring 使用 @AspectJ 注解对POJ...

  • Spring面试常问内容

    Spring 面试问题 TOP 50 IOC、AOP、AOP原理动态代理和cglib原理与二者之间的区别、Bean...

  • Spring动态注册bean

    起因:在使用mybatis 3.2的时候使用了注解式sql;虽然用起来方便 但是这样的bean却不能通过注解来声明...

  • spring动态注册bean

    1 场景 spring运行过程中,有时候需要在程序中动态添加bean。本文主要记录动态添加bean的方式。 2 代...

  • Spring5AOP——AbstractAutoProxyCre

    Spring AOP的总体流程 1、注册解析AOP的服务 2、解析和加载横切逻辑 3、将横切逻辑织入目标Bean中...

网友评论

      本文标题:spring动态注册bean会使AOP失效?

      本文链接:https://www.haomeiwen.com/subject/anpgsrtx.html