您的位置:首页 > 编程语言 > Java开发

spring 源码探索 -- aop 标签解析和创建代理

2016-12-23 01:00 801 查看

aopNamespaceHandler

aop标签和相应的aop parser映射在一起。

注册 AspectJAnnotationAutoProxyCreator

AspectJAutoProxyBeanDefinitionParser
parser
方法实现注册。

AspectJAnnotationAutoProxyCreator的流程

AnnotationAwareAspectJAutoProxyCreator


AnnotationAwareAspectJAutoProxyCreator 是一个BeanPostProcessor实现,它注册的时机是在
AbstractApplicationContext
registerBeanPostProcessors
里面。这个方法会注册spring 容器所有BeanPostProcessor接口的实例。

调用postProcessBeforeInstantiation或者postProcessAfterInitialization

获取增强器 所有的增强器

在增强类的方法上查找aop注解

/**
* Find and return the first AspectJ annotation on the given method
* (there <i>should</i> only be one anyway...)
*/
@SuppressWarnings("unchecked")
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
Class<?>[] classesToLookFor = new Class<?>[] {
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<?> c : classesToLookFor) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {
}


对于不同的增强处理(before,after…),创建不同的实例。

before AspectJMethodBeforeAdvice

使用了MethodBeforeAdviceInterceptor做拦截器,先调用自己的invoke方法,然后再调用真正before的方法

after AspectJAfterAdvice 不一样,直接调用invoke方法。

try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}


寻找匹配的增强器

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}

MethodMatcher methodMatcher = pc.getMethodMatcher();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}

Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}

return false;
}


创建代理

上面的步骤找到了与当前bean匹配的增强器,specificInterceptors,下一步就要开始创建代理了。

从默认aop代理工厂DefaultAopProxyFactory中,根据不同的代理策略来创建aop代理,这里还没有创建代理bean

@Override
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()) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}


使用工厂模式创建aop代理

JdkDynamicAopProxy

典型的jdk 动态代理模式.

构造函数传入目标对象,这里是AdvisedSupport 实例

getProxy

invoke 先获取当前方法的拦截器链,使用
ReflectiveMethodInvocation
封装拦截器链,然后一个个调用。

invocation.proceed();
方法中就是调用增强的方法和目标方法。

if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
}
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}


CGLIB 代理

典型实现

Enhancer.setCallback(MethodInterceptorImpl) 在这里设置拦截器,

Enhancer.create生成代理。

MethodInterceptorImpl 中
proxy.invokeSuper(obj.args)


aop实现

getCallbacks(Class...)
获取拦截器。

将拦截器封装在
DynamicAdvisedInterceptor
中,该类的intercept方法负责处理拦截器的调用,处理的方式和jdk代理中的invoke很类似。

参考:http://www.jianshu.com/p/867991f3daa0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring