上一节我们分析了Advisor的生成过程以及在Advisor中生成Advise的过程。接着上一节继续我们看看挑出适用于目标对象的Advisor:
private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) {
//获取Advisors集合
List advisors = this.aspectFactory.getAdvisors(instanceFactory);
//从中挑出适用于目标对象的Advisor
advisors = AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(advisors);
//对获取到的Advisor进行排序
AnnotationAwareOrderComparator.sort(advisors);
//将获取到Advisor添加到advisors集合中
addAdvisors(advisors);
}
2.3.1:addAdvisorsFromAspectInstanceFactory方法:
a、挑出适用于目标对象的Advisor: AopUtils.findAdvisorsThatCanApply(advisors, getTargetClass());
public static List findAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) {
//如果传入的Advisor集合为空的话,直接返回这个空集合
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
//创建一个合适的Advisor的集合 eligible
List eligibleAdvisors = new LinkedList();
//循环所有的Advisor
for (Advisor candidate : candidateAdvisors) {
//如果Advisor是IntroductionAdvisor 引介增强 可以为目标类 通过AOP的方式添加一些接口实现
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
//是否有引介增强
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
//如果是IntroductionAdvisor类型的话 则直接跳过
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//判断此Advisor是否适用于target
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Advisor advisor, Class> targetClass, boolean hasIntroductions) {
//如果是IntroductionAdvisor的话,则调用IntroductionAdvisor类型的实例进行类的过滤
//这里是直接调用的ClassFilter的matches方法
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
//通常我们的Advisor都是PointcutAdvisor类型
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
//这里从Advisor中获取Pointcut的实现类 这里是AspectJExpressionPointcut
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
这里匹配的规则我们就不进行深入了。
2.4:接着我们来看看代理对象的创建过程:
public class TestAop {
public static void main(String[] args) {
//手工创建一个实例(Target)
ProxyService aspectJService = new ProxyServiceImpl();
//使用AspectJ语法 自动创建代理对象
AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(aspectJService);
//添加切面和通知类
aspectJProxyFactory.addAspect(AopAdviceConfig.class);
//创建代理对象
ProxyService proxyService = aspectJProxyFactory.getProxy();
//进行方法调用
proxyService.testProxy();
}
}
a、创建代理aspectJProxyFactory.getProxy():
//通过调用createAopProxy()生成的对象调用getProxy()方法生成代理对象
public T getProxy() {
return (T) createAopProxy().getProxy();
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
//这里会监听调用AdvisedSupportListener实现类的activated方法
activate();
}
//获取AopProxyFactory
//调用createAopProxy的时候传入了this对象
return getAopProxyFactory().createAopProxy(this);
}
//在SpringAOP中 AopProxyFactory只有一个实现类,这个实现类就是DefaultAopProxyFactory
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
private void activate() {
this.active = true;
for (AdvisedSupportListener listener : this.listeners) {
listener.activated(this);
}
}
b、我们接着看:createAopProxy()方法:
ublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//这段代码用来判断选择哪种创建代理对象的方式
//config.isOptimize() 是否对代理类的生成使用策略优化 其作用是和isProxyTargetClass是一样的 默认为false
//config.isProxyTargetClass() 是否使用Cglib的方式创建代理对象 默认为false
//hasNoUserSuppliedProxyInterfaces目标类是否有接口存在 且只有一个接口的时候接口类型不是SpringProxy类型
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
//从AdvisedSupport中获取目标类 类对象
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的方式生成代理对象
//如果目标类是Proxy类型 则还是使用JDK的方式生成代理对象
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
//使用JDK的提供的代理方式生成代理对象
return new JdkDynamicAopProxy(config);
}
}
c、我们接着往下看看createAopProxy().getProxy()方法:
public T getProxy(ClassLoader classLoader) {
return (T) createAopProxy().getProxy(classLoader);
}
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
//获取AdvisedSupport类型对象的所有接口
Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
//接口是否定义了 equals和hashcode方法 正常是没有的,定义了生成的代理以定义的为准
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//创建代理
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
private void findDefinedEqualsAndHashCodeMethods(Class>[] proxiedInterfaces) {
for (Class> proxiedInterface : proxiedInterfaces) {
Method[] methods = proxiedInterface.getDeclaredMethods();
for (Method method : methods) {
if (AopUtils.isEqualsMethod(method)) {
this.equalsDefined = true;
}
if (AopUtils.isHashCodeMethod(method)) {
this.hashCodeDefined = true;
}
if (this.equalsDefined && this.hashCodeDefined) {
return;
}
}
}
}
e、我们知道创建代理需要额外功能类继承InvocationHandler实现invoke方法添加额外功能,那么我们来看看JdkDynamicAopProxy中的invoke的实现:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
//目标对象
TargetSource targetSource = this.advised.targetSource;
Class> targetClass = null;
Object target = null;
try {
//接口中没有定义 equals方法,并且调用的方法是equals方法(即Object中定义的equals方法)
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
//调用 JdkDynamicAopProxy 中写的equals方法
return equals(args[0]);
}else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
//和上面的分析一样
return hashCode();
}else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
//如果 方法所在的类是接口 并且是Advised的子类,则直接调用下面的方法
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//是否对外暴露代理对象
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
//把创建的代理对象放到线程上下文中返回之前老的代理
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//从TargetSource中获取目标对象
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
//从Advised中根据方法名和目标类获取 AOP拦截器执行链 重点要分析的内容
List
从上面代码不难看出这段代码的重点:从Advised中根据方法名和目标类获取 AOP拦截器执行链(List
f、this.advised.getInterceptorsAndDynamicInterceptionAdvice:
public List
从上面代码可以总结下流程:
1、循环目标方法的所有Advisor
2、判断Advisor的类型
a、如果是PointcutAdvisor的类型,则判断此Advisor是否适用于此目标方法
b、如果是IntroductionAdvisor引介增强类型,则判断此Advisor是否适用于此目标方法
c、如果以上都不是,则直接转换为Interceptor类型。
不管是Advisor哪一类型最终都会registry.getInterceptors(advisor);进行转换,那么我们来看看这个方法:
g、registry.getInterceptors(advisor):
我们来先看看registry的获取代码:
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
=========
public abstract class GlobalAdvisorAdapterRegistry {
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
=========
public DefaultAdvisorAdapterRegistry() {
//前置通知适配器
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
//后置返回通知适配器
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
//后置异常通知适配器
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
接着我们来看看:registry.getInterceptors的代码:
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List interceptors = new ArrayList(3);
//从Advisor中获取 Advice
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
//转换为对应的 MethodInterceptor类型
//AfterReturningAdviceInterceptor MethodBeforeAdviceInterceptor ThrowsAdviceInterceptor
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
l、拦截器连的调用过程:
invoke方法中的:
//如果AOP拦截器执行链不为空 说明有AOP通知存在
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//开始调用
retVal = invocation.proceed();
那么我们来看看这个方法:
public Object proceed() throws Throwable {
// 如果执行到链条的末尾则直接调用连接点方法即直接调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//调用目标方法
return invokeJoinpoint();
}
//获取集合中的 MethodInterceptor
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果是InterceptorAndDynamicMethodMatcher类型
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
//这里每一次都去匹配是否适用于这个目标方法
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
//如果匹配则直接调用 MethodInterceptor的invoke方法
return dm.interceptor.invoke(this);
}
else {
//如果不适用于此目标方法 则继续执行下一个链条 递归调用
return proceed();
}
}
else {
//直接调用 MethodInterceptor的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
看下invokeJoinpoint方法(直接掉用目标类的方法):
protected Object invokeJoinpoint() throws Throwable {
//this.target 目标对象
//this.method 目标方法
this.arguments 目标方法参数信息
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
//设置方法可见性
ReflectionUtils.makeAccessible(method);
//反射调用 最终是通过反射去调用目标方法
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}