Spring AOP 嵌套代理 - 用BeanPostProce

2020-05-06  本文已影响0人  overflowedstack
在实际应用中,经常遇见需要嵌套代理的场景:

方法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来实现。
@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);
}
@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;
上一篇下一篇

猜你喜欢

热点阅读