首先配置文件内容如下:
<!--横切逻辑--> <bean id="logUtils" class="com.test.circular.LogUtils"> </bean> <aop:config> <aop:aspect ref="logUtils"> <aop:before method="beforeMethod" pointcut="execution(public void com.test.aop.AopBean.test())"/> <aop:after method="alertMethod" pointcut="execution(public void com.test.aop.AopBean.test())"/> <aop:around method="aroundMethod" pointcut="execution(public void com.test.aop.AopBean.test())"/> <aop:after-returning method="afterReturning" pointcut="execution(public void com.test.aop.AopBean.test())"/> <aop:after-throwing method="afterThrowingMethod" pointcut="execution(public void com.test.aop.AopBean.test())"/> </aop:aspect> </aop:config>
public class LogUtils { public void beforeMethod() { System.out.println("前置通知"); } public void alertMethod() { System.out.println("最终通知"); } public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable { System.out.println("环绕通知-前"); Object proceed = pjp.proceed(); System.out.println("环绕通知-后"); return proceed; } public void afterThrowingMethod() { System.out.println("异常通知"); } public void afterReturning() { System.out.println("后置通知"); } }
public class AopBean implements AopBeanInf{
@Override
public void test() {
System.out.println("spring aop 测试");
}
}
通过SpringIOC源码中的源码分析过程,可以将切入点定位到如下图所示方法。
接着会遍历所有的初始化的bean,主要进入AbstractAutowireCapableBeanFactory的doCreateBean方法,会完成实例创建。
往下走会完成bean生命周期的管理,首先属性填充,调用初始化bean,重点分析这个方法。
1) 调用Bean中的BeanNameAware.setBeanName()方法,如果该Bean实现了BeanNameAware接口;调用Bean中的BeanFactoryAware.setBeanFactory()方法,如果该Bean实现了BeanFactoryAware接口,调用Bean中的BeanClassLoader.setBeanClassLoader()方法。
2)调用BeanPostProcessors.postProcessBeforeInitialization()方法
3)调用Bean中的afterPropertiesSet方法,如果该Bean实现了InitializingBean接口;
4)调用Bean中的init-method,通常是在配置bean的时候指定了init-method,例如:<beanclass="beanClass"init-method="init"></bean>
5)调用BeanPostProcessors.postProcessAfterInitialization()方法;
实现AOP主要在初始化后应用Bean后置处理器---在这一步生成代理对象
这个方法会遍历所有的后置处理器。
主要进入AbstractAutoProxyCreator类的postProcessAfterInitialization方法,如下红框所示对象进行包装即增强
将所有的通知拆分成数组。
如下图所示,通过createProxy方法创建代理对象。
进入的createProxy方法,该方法中主要有getProxy这个方法中会通过代理工厂生成对象
判断是否实现接口,用jdk还是cglib代理,默认采用jdk代理。
public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
创建代理对象后,这里采用JdkDynamicAopProxy,然后进入该类的getProxy执行代理方法
观察下JdkDynamicAopProxy这个类,本身实现了InvocationHandler,就是个代理对象,
作为Proxy对象的回调函数被触发,从而通过invoke()的具体实现来完成对目标对象的拦截或者说功能增强的工作。
执行代理对象的invoke方法。
得到拦截链。
递归进入了ReflectiveMethodInvocation类的proceed()
可以看到此时的methodName为beforeMethod
因此此时会执行MethodBeforeAdviceInterceptor类的invoke方法。
继续往下走,一直到AbstractAspectJAdvice类的如下方法:
通过反射执行Method
执行到DelegatingMethodAccessorImpl类的invoke方法。
执行到NativeMethodAccessorImpl类中invoke方法。
继续执行会到走到前置通知方法答应出具体内容。
返回,执行完前置通知后再调用mi.proceed()。
接着从执行链中再取一个执行。
进入AspectJAfterAdvice类执行最终通知
环绕通知,创建了连接点对象,执行到AspectJAroundAdvice类的invoke方法
进入proceed,执行后置通知
AfterReturningAdviceInterceptor
执行连接点之后进行后置通知,首先执行连接点方法
这时找到异常通知
在AspectJAfterThrowingAdvice类
执行目标方法
然后返回
执行后置通知
最后在finally中执行最终通知。