美文网首页
Spring AOP 嵌套代理 - 用BeanPostProce

Spring AOP 嵌套代理 - 用BeanPostProce

作者: overflowedstack | 来源:发表于2020-05-06 21:09 被阅读0次
    在实际应用中,经常遇见需要嵌套代理的场景:

    方法hello内部调用方法goodbye,同时,方法hello和goodbye都做了增强。

        public void hello() {
                System.out.println("Hello,IOC");
                goodbye();
        }
        public void goodbye() {
                System.out.println("Goodbye");
        }
    
        @Pointcut("execution(public * io.github.dunwu.spring.core.aop.example.IOCServiceImpl.hello(..))")
        public void testAOP1(){
        }
    
        @Around("testAOP1()")
        public Object around(ProceedingJoinPoint p){
            System.out.println("around before testAOP1...");
            Object o = null;
            try {
                o = p.proceed();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            System.out.println("around after testAOP1...");
            return o;
        }
    
        @Pointcut("execution(public * io.github.dunwu.spring.core.aop.example.IOCServiceImpl.goodbye(..))")
        public void testAOP2(){
        }
    
        @Around("testAOP2()")
        public void around(ProceedingJoinPoint p){
            System.out.println("around before testAOP2...");
            Object o = null;
            try {
                p.proceed();
            } catch (Throwable e) {
                e.printStackTrace();
            }
            System.out.println("around after testAOP2...");
            return o;
        }
    

    调用hello方法时,会发生什么呢?
    只有hello方法被增强了,goodbye方法直接被调用,并没有被增强。输出如下:

    around before testAOP1...
    Hello,IOC
    Goodbye
    around after testAOP1...
    
    问题来了,为什么goodbye方法没有被增强?

    这是因为hello方法被增强之后,invoke hello方法时,调用goodbye其实是调用this.goodbye方法,也就是原始方法而并不是被增强的方法。

    那么如果需要实现嵌套代理,该怎么做呢?可以用BeanPostProcessor来实现。
    • 定义接口BeanSelfAware。目标类继承BeanSelfAware接口,实现setSelf方法,将代理对象set给self。在hello内部调用self.goodbye()方法。
    @Component
    public class IOCServiceImpl implements IOCService, BeanSelfAware {
        @Autowired
        private IOCService self;
        
        public void hello() {
                System.out.println("Hello,IOC");
                self.goodbye();
        }
        
        public void goodbye() {
                System.out.println("Goodbye");
        }
    
        @Override
        public void setSelf(Object proxyBean) {
            this.self = (IOCService) proxyBean;
        }
    }
    
    public interface BeanSelfAware {
        void setSelf(Object proxyBean);
    }
    
    • 自定义bean post processor,对于实现BeanSelfAware的类,调用其setSelf方法,将代理类传过去。
    @Component
    public class InjectBeanSelfProcessor implements BeanPostProcessor{
        
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException  
        {  
            if(bean instanceof BeanSelfAware)  
            {  
                System.out.println("inject proxy:" + bean.getClass());  
                BeanSelfAware myBean = (BeanSelfAware)bean;  
                myBean.setSelf(bean);  
                return myBean;  
            }  
            return bean;  
        }  
       
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException  
        {  
            return bean;  
        }
    }
    
    • 这时,调用目标方法,会发现两个方法都被增强了。
    around before testAOP1...
    Hello,IOC
    around before testAOP2...
    Goodbye
    around after testAOP2...
    around after testAOP1...
    
    这个解决方案的底层原理是什么?

    BeanPostProcessor是一个接口,有两个方法。

    public interface BeanPostProcessor {
        @Nullable
        default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
        @Nullable
        default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    }
    

    Spring容器初始化时,registerBeanPostProcessors(beanFactory)底层,会扫描所有实现了BeanPostProcessor接口的类,注册为bean post processor。

            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);
    

    在创建bean,进行初始化的时候,会依次调用注册的bean后置处理器,当调用到自定义的后置处理器InjectBeanSelfProcessor时,bean已经成为了被代理的对象,这时,将代理对象赋值给self成员变量,就可以在后面用self.goodbye来实现嵌套代理。

    说了这么多,其实效果跟@Autowired一样,也能做到嵌套代理。

    这里自动装配的就是一个代理对象。后面通过self.goodbye调用,也一样调用的是代理类的方法。

    @Autowired
    private IOCService self;
    

    相关文章

      网友评论

          本文标题:Spring AOP 嵌套代理 - 用BeanPostProce

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