项目搭建
为了更好地阐述AOP的原理,这里我们来实现一个简单地需求,计算除法。 下面的代码中分别创建了一个计算类和一个计算代理类,熟悉SpringAOP开发的读者应该非常熟悉下面的代码格式。
实现下面的代码需要添加依赖:
compile group: 'org.aspectj', name: 'aspectjweaver', version: '1.9.5'compile group: 'org.springframework', name: 'spring-context', version: '5.2.6.RELEASE'
定义 MathCalculator 用户被代理,实现一个整数的除法;定义 MathCalculatorAspect 用户实现AOP 代理,切入点 execution(public double com.zhoutao123.spring.aop.MathCalculator.*(..)) 分别实现前置通知,后置通知,环绕通知以及异常通知(其他通知方式,读者可以自己实现测试)
// 定义目标代理类public class MathCalculator {public double div(Integer a, Integer b) {System.out.println("调用业务代码");return a * 1.0 / b;}}// 定义代理类@Aspectpublic class MathCalculatorAspect {@Pointcut("execution(public double com.zhoutao123.spring.aop.MathCalculator.*(..))")public void pointCut() {}@Before("pointCut()")public void before(JoinPoint joinPoint) {Signature signature = joinPoint.getSignature();System.out.println("Before 方法名称:" + signature.getName() + " 参数表:" + Arrays.toString(joinPoint.getArgs()));}@After("pointCut()")public void after() {System.out.println("后置执行");}@AfterReturning(value = "pointCut()", returning = "result")public void afterReturning(Object result) {System.out.println("返回值:" + (result == null ? "null" : result.toString()));}@AfterThrowing(value = "pointCut()", throwing = "exception")public void afterThrowing(Exception exception) {System.out.println("异常信息:" + (exception == null ? "null" : exception.getMessage()));}}
同时需要创建一个配置类,用于启动Spring项目以及注入 MathCalculator & MathCalculatorAspect ,执行main方法可以看到代理日志的输出
@Configurable@EnableAspectJAutoProxypublic class MainConfigOfAOP {@Beanpublic MathCalculator matchCalculator() {return new MathCalculator();}@Beanpublic MathCalculatorAspect aspect() {return new MathCalculatorAspect();}public static void main(String[] args) {AnnotationConfigApplicationContextcontext = new AnnotationConfigApplicationContext(MainConfigOfAOP.class);MathCalculator bean = context.getBean(MathCalculator.class);bean.div(1, 0);}}// 输出日志Before 方法名称:div 参数表:[18, 3]调用业务代码后置执行返回值:6.0
源码分析
细心地读者可能发现,在MainConfigOfAOP的类中,出现了一个注解 @EnableAspectJAutoProxy 这个注解使用常见的SPring提供的 @EnableXXXX 类型的注解,这个注解非常重要,使用@Import注解 导入需要的Bean类型对象。
@Configurable@EnableAspectJAutoProxypublic class MainConfigOfAOP {}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(AspectJAutoProxyRegistrar.class)public @interface EnableAspectJAutoProxy {}
EnableAspectJAutoProxy 注解
如上文所示,EnableASpectJAutoProxy注解导入 @Import(AspectJAutoProxyRegistrar.class 而 AspectJAutoProxyRegistrar 是一个 ImportBeanDefinitionRegistrar ,ImportBeanDefinitionRegistrar 可以向IOC中注册BeanDefinition。AspectJAutoProxyRegistrar 会向Spring的容器中注入一个类型为 AnnotationAwareAspectJAutoProxyCreator 的BeanPostProcessor(后置处理器)用户处理Bean对象。

关于 ImportBeanDefinitionRegistrar 导入Bean的注册器 以及 BeanPostProcessor 后置处理器,在笔者的同栏文章,均有详细的阐述,对这里不太明白的,可以查阅这些文章或者留言!
@Nullableprivate static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {// .....RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;}
AnnotationAwareAspectJAutoProxyCreator 是一个后置处理器,继承了 BeanPostProcessor ,AspectJAutoProxyRegistrar 想SpringIOC 注入这个Bean的定义之后,Sprin会在之后创建这个对象实例。
Spring容器启动
容器启动后AnnotationAwareAspectJAutoProxyCreator 被创建,并且被收到IOC 的后置处理器集合中,然后继续执行创建Bean,创建Bean的过程中获取遍历后置处理器,分别来进行处理这些Bean。
// 所在类 org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.remove(cacheKey) != bean) {// 调用方法,判断是否需要封装(即是否需要被代理)return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// .......// 获取增强点,如果增强点不存在,则不在创建代理,否则执行createProxy() 方法创建代理对象Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}
而创建代理对象createProxy() 方法的核心类为 ProxyFactory
**
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {//....ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);// 获取增强点信息Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);// 封装到 ProxyFactory 中proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);// 模板方法,忽略customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// 生成代理对象return proxyFactory.getProxy(getProxyClassLoader());}
众所周知,Spring生成代理对象有两种方式: JDK & Cglib, DefaultAopProxyFactory 的代码中提供了说明
@Overridepublic 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.");}// 如果代理类是接口 或者 是一个代理类,则直接走JDK动态代理,否则走Cglib代理if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}
JDK 方式实现动态代理
JDK的动态代理是通过实现 InvocationHandler实现了,然后重写invoke方法,这和我们之前的项目中使用JDK动态代理的方式是一致的。
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {// ...... 省略代码@Override@Nullablepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Object target = null;// 获取目标方法的拦截链List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);// 如果拦截链为空,则使用反射的方法执行,否则生成MethodInvocation,进行执行if (chain.isEmpty()) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}else {MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);retVal = invocation.proceed();}
Cglib 方式实现动态代理
Cglib 动态代理是基于字节码实现的,因此性能相对于JDK代理而言较高。一般情况下,Cglib的代理生成类如下所示:
// 定义拦截器public class MyMethodInterceptor implements MethodInterceptor{@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("调用代理方法");return proxy.invokeSuper(obj, args);}}//创建Enhancer对象,类似于JDK动态代理的Proxy类,下一步就是设置几个参数Enhancer enhancer = new Enhancer();//设置目标类的字节码文件enhancer.setSuperclass(Cat.class);//设置回调函数enhancer.setCallback(new MyMethodInterceptor());//这里的creat方法就是正式创建代理类Cat proxyCat = (Cat)enhancer.create();//调用代理类的eat方法proxyCat.eat();
而在Sprint中使用CGlib实现代理的方式也是大同小异,具体分析如下:
@Overridepublic Object getProxy() {return getProxy(null);}@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());}try {// 获取代理目标类Class<?> rootClass = this.advised.getTargetClass();// Configure CGLIB Enhancer...Enhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}// 设置Cglib代理的目标类等配置信息enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));// 生成回调方法Callback[] callbacks = getCallbacks(rootClass);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// 直接生成代理类,并返回实例对象return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class",ex);}catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}}protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {enhancer.setInterceptDuringConstruction(false);enhancer.setCallbacks(callbacks);return (this.constructorArgs != null && this.constructorArgTypes != null ?enhancer.create(this.constructorArgTypes, this.constructorArgs) :enhancer.create());}
