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是一个什么东西呢,让我们点进去继续查看 发先其继承关系如下
发现它有一个顶层接口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
通过源码可知我们先将代理对象、代理目标、调用方法、参数和通知链封装成一个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代理源码实现简要分析。