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很类似。