在实际应用中,经常遇见需要嵌套代理的场景:
方法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;
网友评论