Spring专题: 3. Spring AOP动态代理的原理
2019-01-05 本文已影响0人
北交吴志炜
先上代码,比如我使用aspectj风格的注解,定义了一个针对naiveWaiter的切面逻辑
@Aspect
public class TestAspect {
/**
* 访问连接点对象
*/
@Around("execution(* greetTo(..)) && target(com.brianway.learning.spring.aop.aspectj.NaiveWaiter)")
public void joinPointAccess(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("------joinPointAccess-------");
System.out.println("args[0]:" + pjp.getArgs()[0]);
System.out.println("target:" + pjp.getTarget());
System.out.println("signature:" + pjp.getSignature());
System.out.println("this:" + pjp.getThis());
pjp.proceed();
System.out.println("-------joinPointAccess-------");
}
测试类如下
@Test
public void testJoinPoint() {
String configPath = "com/brianway/learning/spring/aop/aspectj/beans-advanced.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(configPath);
Waiter naiveWaiter = (Waiter) context.getBean("naiveWaiter");
naiveWaiter.greetTo("Brian");
}
debug看一下这个naiveWaiter对象到底是什么

可以看到这个naiveWaiter对象其实是一个EnhancerBySpringCglib
并不是一个普通的NaiveWaiter对象,关键点就在这里。
当一个对象被SpringAOP代理,那么当使用getBean获取到的并不是对象本身,而是一个代理对象。
那么之前的文章bean的生命周期中,这个代理的过程是在哪一步进行的呢
createBeanInstance
populateBean
initlizeBean
其实发生在initlizeBean,在其中会执行BeanProcessor.postProcessAfterInitialization
具体就是AbstractAutoProxyCreator类的postProcessAfterInitialization 方法
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
} else if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
} else if (!this.isInfrastructureClass(bean.getClass()) && !this.shouldSkip(bean.getClass(), beanName)) {
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
} else {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
}
执行之后,返回的就是一个代理对象(代理对象包含一个Advisor数组,一个目标对象)
总结一下,Spring AOP动态代理的执行过程如下
1.生成代理对象,初始化拦截器链(这发生在bean的生命周期initlizeBean中,生成是通过AopProxy接口,有两个实现类Cglib2AopProxy,JdkDynamicAopProxy)
2.代码中调用bean的某个方法的时候,实际上是通过代理对象调用的。调用时会获取拦截器链,逐个进行匹配执行(切面逻辑),最终通过反射的方法调用目标对象方法。