如果需要在Spring中使用AOP是非常简单的,只需要在Bean上加上@AspectJ,在方法上加@PointCut、@Before等注解就可以实现你想要的逻辑,最后在XML配置文件中加入<aop:aspectj-autoproxy>
即可。
那么Spring是如何实现的呢?
动态AOP标签
我们从AopNamespaceHandler中的init()方法开始分析:
1.配置文件中在遇到aspectj-autoproxy标签的时候我们会采用AspectJAutoProxyBeanDefinitionParser解析器
2.进入AspectJAutoProxyBeanDefinitionParser的parse方法,它将请求给了AopNamespaceUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary去处理
3.registerAspectJAnnotationAutoProxyCreatorIfNecessary方法中,先调用AopConfigUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法完成注册或者升级AnnotationAwareAspectJAutoProxyCreator类。对于AOP的实现,基本是靠AnnotationAwareAspectJAutoProxyCreator去完成的,它可以根据@point注解定义的切点来代理相匹配的bean。
4.接下来会调用useClassProxyingIfNecessary() 处理proxy-target-class以及expose-proxy属性
5.最后的调用registerComponentIfNecessary 方法,注册组建并且通知便于监听器做进一步处理。
2.创建AOP代理
AOP主要是依靠AnnotationAwareAspectJAutoProxyCreator的实现的。那么AnnotationAwareAspectJAutoProxyCreator是如何完成的?
AnnotationAwareAspectJAutoProxyCreator的层次结构:
AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,那就意味着这个类在spring加载实例化前会调用postProcessAfterInitialization方法。
public Object <strong>postProcessAfterInitialization</strong>(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.containsKey(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
逻辑:
1.根据bean的class和name生成一个key。
2.如果适合代理就执行wrapIfNecessary(bean, beanName, cacheKey)。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
逻辑:
1.如果以及处理过直接返回bean
2.不需要advisor返回bean
3.如果是基类或者说不需要自动代理返回bean。
4.获得此类的advisor
5.创建代理
2.1 getAdvicesAndAdvisorsForBean
getAdvicesAndAdvisorsForBean主要逻辑由findEligibleAdvisors实现
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
2 List<Advisor> candidateAdvisors = findCandidateAdvisors();
3 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
4 extendAdvisors(eligibleAdvisors);
5 if (!eligibleAdvisors.isEmpty()) {
6 eligibleAdvisors = sortAdvisors(eligibleAdvisors);
7 }
8 return eligibleAdvisors;
9 }
findEligibleAdvisors实现逻辑:
1.findCandidateAdvisors找到所有的Advisors
2.findAdvisorsThatCanApply找到匹配当前bean的Advisors。
findCandidateAdvisors源码逻辑:
1.获得beanFactory中注册所有的BeanName
2.遍历所有BeanName,找出有@AspectJ的类
3.对有@AspectJ的类提取advisor
4.将提取出的结果放入缓存。
findAdvisorsThatCanApply源码逻辑:
从findCandidateAdvisors获得的advisor中寻找适合当前class的advisor。
2.2 createProxy
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
proxyFactory.copyFrom(this);
if (!shouldProxyTargetClass(beanClass, beanName)) {
// Must allow for introductions; can't just set interfaces to
// the target's interfaces only.
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
for (Class<?> targetInterface : targetInterfaces) {
proxyFactory.addInterface(targetInterface);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.<strong>setTargetSource</strong>(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//实现核心方法
return proxyFactory.getProxy(this.proxyClassLoader);
}
通过上面的源码我们可以知道,对于代理的创建,Springle交给了proxyFactory的getProxy方法去完成,而之前的所有主要是为proxyFactory做了初始准备而已。
2.2.1 ProxyFactory.getProxy(classLoader)
public object getProxy(ClassLoader classLoader){
return createAopProxy().getProxy(classLoader);
}
createAopProxy创建代理:
protected final synchronized AopProxy createAopProxy(){
if(!this.active){activate();}
return getAopProxyFactory().createAopProxy(this);
}
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 CglibProxyFactory.createCglibProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
上述代码中的if判断主要是对代理的选择,使用JDK或者CGLIB实现代理,选择完以后就创建了代理。
- **optimize:**CGLIB创建的代理是否使用激进策略。
- proxyTargetClass:当XML配置文件设置了
<aop:aspectj-autoproxy proxy-target-class="true"/>
时为true,表示使用CGLIB - hasNoUserSuppliedProxyInterfaces:是否存在代理接口。
获得代理
我们以使用JDK获得代理做一下分析:
使用JDK方式最关键两个方法:invoke和getProxy。
getProxy:获得代理对象。
invoke:执行被代理对象的方法。
我们看一下JdkDynamicAopProxy的核心代码invoke方法:
public Object invoke(Object proxy, Method method, Object[] args) throwsThrowable {
MethodInvocation invocation = null;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class targetClass = null;
Object target = null;
try {
//eqauls()方法,具目标对象未实现此方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)){
return (equals(args[0])? Boolean.TRUE : Boolean.FALSE);
}
//hashCode()方法,具目标对象未实现此方法
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)){
return newInteger(hashCode());
}
//Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
if (!this.advised.opaque &&method.getDeclaringClass().isInterface()
&&method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations onProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised,method, args);
}
Object retVal = null;
if (this.advised.exposeProxy) {
// Make invocation available ifnecessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//获得目标对象的类
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
//获取当前方法的拦截链
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method,targetClass);
//如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)
if (chain.isEmpty()) {
retVal = AopUtils.invokeJoinpointUsingReflection(target,method, args);
} else {
//创建MethodInvocation,封装拦截器链
invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
// Massage return value if necessary.
if (retVal != null && retVal == target &&method.getReturnType().isInstance(proxy)
&&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned"this" and the return type of the method
// is type-compatible. Notethat we can't help if the target sets
// a reference to itself inanother returned object.
retVal = proxy;
}
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
// Must have come fromTargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
1)获取拦截器:getInterceptorsAndDynamicInterceptionAdvice
2)判断拦截器链是否为空,如果是空的话直接调用切点方法
3)如果拦截器不为空的话那么便创建ReflectiveMethodInvocation类,把拦截器方法都封装在里面
4)对拦截器链中的拦截器逐一调用:invocation.proceed()
看一下proceed方法:
public Object proceed() throws Throwable {
// We start with an index of -1and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()- 1) {
//如果Interceptor执行完了,则执行joinPoint
return invokeJoinpoint();
}
//获得下一个拦截器interceptor
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果要动态匹配joinPoint
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher){
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
//动态匹配:运行时参数是否满足匹配条件
if (dm.methodMatcher.matches(this.method, this.targetClass,this.arguments)) {
//执行当前Intercetpor
returndm.interceptor.invoke(this);
}
else {
//动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
return proceed();
}
}
else {
//对于普通拦截器
//执行当前Intercetpor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
ReflectiveMethodInvocation中维护了拦截器调用的计数器,用来记录当前调用链接的位置,使得可以有序的对拦截器逐一调用。
实现Aop自动代理总结:
1.<aop:aspectj-autoproxy/>
解析注册AnnotationAwareAspectJAutoProxyCreator类
2.AnnotationAwareAspectJAutoProxyCreator完成动态代理
AnnotationAwareAspectJAutoProxyCreator完成动态代理实现逻辑:
2.1.执行postProcessAfterInitialization()
———–如果适合代理就执行wrapIfNecessary()方法。
2.1.1wrapIfNecessary()实现逻辑:
1.判断是否需要生成代理
2.如果需要则调用getAdvicesAndAdvisorsForBean()方法获得当前类的advisor
3调用createProxy()创建代理。
2.1.1.2getAdvicesAndAdvisorsForBean()逻辑:
主要交给findEligibleAdvisors,实现逻辑:
—-1.findCandidateAdvisors找到所有的Advisors
—-2.findAdvisorsThatCanApply找到匹配当前bean的Advisors。
findCandidateAdvisors源码逻辑:
—-1.获得beanFactory中注册所有的BeanName
—-2.遍历所有BeanName,找出有@AspectJ的类
—-3.对有@AspectJ的类提取advisor
—-4.将提取出的结果放入缓存。
findAdvisorsThatCanApply源码逻辑:
—-从findCandidateAdvisors获得的advisor中寻找适合当前class的advisor。
2.1.1.3.调用createProxy()创建代理实现逻辑:
—-1.对ProxyFactory进行初始化
—-2.调用ProxyFactory.getProxy()创建代理
2.1.1.3.2.ProxyFactory.getProxy()实现逻辑:
调用 createAopProxy.getProxy(classLoader),逻辑如下
—-1.创建AopProxy:
——-对实现代理方式进行选择:JDK?CGLIB?
——-调用JdkDynamicAopProxy的构造方法获得代理。
JdkDynamicAopProxy的invoke方法:
1)获取拦截器:getInterceptorsAndDynamicInterceptionAdvice
2)判断拦截器链是否为空,如果是空的话直接调用切点方法
3)如果拦截器不为空的话那么便创建ReflectiveMethodInvocation类,把拦截器方法都封装在里面
4)对拦截器链中的拦截器逐一调用:invocation.proceed()
proceed()方法:ReflectiveMethodInvocation中维护了拦截器调用的计数器,用来记录当前调用链接的位置,使得可以有序的对拦截器逐一调用。