(二)Spring源码解析--AOP

AOP为我们提供无侵入的切面编程能力,在Spring中通过切面可以完成事务控制等功能,下面我们一起来分析Spring中AOP的实现原理。

我们以注解版的切面配置为例,若想实现AOP功能,首先我们需要定义一个如下的切面类:我们通过注解@Aspect标注切面,通过@Component将此切面作为Spring容器组件

@Aspect
@Component
public class Audience {

	@Pointcut("execution(* aop.Performance.perform(..))")
	public void performance(){}

	@Before("performance()")
	public void beforePerform(){
		System.out.println("在表演开始之前,请领导讲话!");
	}

	@After("performance()")
	public void afterPerform(){
		System.out.println("表演完成后,大家鼓掌感谢!");
	}

}

若想使用AOP注解功能,还需要开启注解代理如下所示:通过注解@EnableAspectJAutoProxy启用AOP功能

@Configurable
@ComponentScan(basePackages = {"aop"},excludeFilters = {
		@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class})
})
@EnableAspectJAutoProxy
public class SpringConfig {

}

 查看注解@EnableAspectJAutoProxy发现其引入了组件类AspectJAutoProxyRegistrar.class

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;
}

进入AspectJAutoProxyRegistrar.class发现器主要是向容器中注册了一个创建器,那么是什么创建器?继续跟进查看发现其实际是向容器中注册了一个AnnotationAwareAspectJAutoProxyCreator创建其

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //重点:向注册中心注册一个创建器
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
        }

        if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
            AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
        }

    }

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
        // 重点:注册AnnotationAwareAspectJAutoProxyCreator
        return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    }

AnnotationAwareAspectJAutoProxyCreator是一个什么东西呢,让我们点进去继续查看 发先其继承关系如下

(二)Spring源码解析--AOP_第1张图片

发现它有一个顶层接口InstantiationAwareBeanPostProcessor,这个接口我们在第一节IOC容器初始时就已经非常熟悉了,它会在bean实例化前后和初始化前后执行,在AbstractAutoProxyCreator中对接口方法进行了实现,最终代理类生成是在postProcessAfterInitialization中的this.wrapIfNecessary()中

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return this.wrapIfNecessary(bean, beanName, cacheKey);
            }
        }

        return bean;
    }

wrapIfNecessary()会调用createProxy()方法生成代理对象

 Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

createProxy()方法,如下源码所示如果有接口会选择JDK动态代理,没有接口会选择CGLIB生成动态代理

// 通过AopProxy创建代理
 public Object getProxy(ClassLoader classLoader) {
        return this.createAopProxy().getProxy(classLoader);
    }

// 1. 有接口选择JDK动态代理 没有接口选择cglib生成动态代理

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
            return new JdkDynamicAopProxy(config);
        } else {
            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.");
            } else {
                return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
            }
        }
    }

//2. JDK动态代理生成
 public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }

        Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
        this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

 通过getProxy就得到了我们的代理对象了,下面我们将分析如代理对象方法调用流程:

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object oldProxy = null;
        boolean setProxyContext = false;
        TargetSource targetSource = this.advised.targetSource;
        Class targetClass = null;
        try {
                
               ...............................................
                // 得到方法通知链
                List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
                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();
                }
        return var10;
    } 
  

通过源码可知我们先将代理对象、代理目标、调用方法、参数和通知链封装成一个MethodInvocation接口(ReflectiveMethodInvocation)对象并调用proceed()方法进行执行:

public Object proceed() throws Throwable {
        if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
            return this.invokeJoinpoint();
        } else {
            Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
                return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
            } else {
                return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    }

这里其实设计是比较巧妙的,每次从interceptorsAndDynamicMethodMatcher通知链中拿出一个通知(不同通知是不同类型的对象),如果是before则进入MethodBeforeAdviceInterceptor对象的invoke方法

public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
    private MethodBeforeAdvice advice;

    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }
    
    public Object invoke(MethodInvocation mi) throws Throwable {
        // 先调用前置通知方法
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
        // 在递归调用处理进程
        return mi.proceed();
    }
}

如果是after则进入AspectJAfterAdvice的invoke执行方法

public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {
    public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
        super(aspectJBeforeAdviceMethod, pointcut, aif);
    }

    public Object invoke(MethodInvocation mi) throws Throwable {
        Object var2;
        try {
            // 继续递归调用处理进程
            var2 = mi.proceed();
        } finally {
            // 递归出来后执行后置方法
            this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
        }

        return var2;
    }
}

通知链执行完后就完成了AOP代理对象的执行,以上就是AOP代理源码实现简要分析。

 

你可能感兴趣的:(java基础)