目录
@EnableAspectJAutoProxy找切面代理对象的创建代理方法的执行ExposeInvocationInterceptor#invoke环绕通知的执行前置通知的执行后置通知的执行返回后通知的执行异常通知的执行@EnableAspectJAutoProxy
@EnableAspectJAutoProxy注解用于开启AOP功能,那么这个注解底层到底做了什么呢?
查看@EnableAspectJAutoProxy的源码,发现它使用@Import注解向Spring容器中注入了一个类型为AspectJAutoProxyRegistrar的Bean:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 注入一个bean名字为org.springframework.aop.config.internalAutoProxyCreator的AspectJAwareAdvisorAutoProxyCreator
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
// proxyTargetClass为true
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
// exposeProxy为true
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,而ImportBeanDefinitionRegistrar是spring提供的扩展点之一,主要用来向容器中注入BeanDefinition,spring会根据BeanDefinion来生成Bean。
那么AspectJAutoProxyRegistrar到底向容器中注入了什么BeanDefinion呢?
org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry)
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// AnnotationAwareAspectJAutoProxyCreator
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
// 注入AspectJAwareAdvisorAutoProxyCreator
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}从源码可以发现AspectJAutoProxyRegistrar向容器中注入了一个类型为AnnotationAwareAspectJAutoProxyCreator的Bean。
那么AnnotationAwareAspectJAutoProxyCreator又是干什么的呢?
AnnotationAwareAspectJAutoProxyCreator主要实现了三个接口(由父类AbstractAutoProxyCreator实现):
AnnotationAwareAspectJAutoProxyCreator的继承结构:
找切面
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected ListfindEligibleAdvisors(Class> beanClass, String beanName) { /** * @see AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors() */ // 获取容器中所有的切面Advisor // 这里返回的切面中的方法已经是有序的了,先按注解顺序(Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),再按方法名称 List candidateAdvisors = findCandidateAdvisors(); // 获取所有能够作用于当前Bean上的Advisor List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); /** * @see AspectJAwareAdvisorAutoProxyCreator#extendAdvisors(java.util.List) */ // 往集合第一个位置加入了一个DefaultPointcutAdvisor extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { /** * @see AspectJAwareAdvisorAutoProxyCreator#sortAdvisors(java.util.List) */ // 这里是对切面进行排序,例如有@Order注解或者实现了Ordered接口 eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
protected ListfindCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. // 获取容器中所有的切面Advisor List advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { // 这里还需要解析@Aspect注解,生成Advisor advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply
public static ListfindAdvisorsThatCanApply(List candidateAdvisors, Class> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List eligibleAdvisors = new ArrayList<>(); // InstantiationModelAwarePointcutAdvisorImpl for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { // IntroductionAdvisor类型为引入切面,具体类型为DeclareParentsAdvisor eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } // PointCut中的ClassFilter.match 匹配类 // PointCut中的MethodMatcher.match 匹配方法 if (canApply(candidate, clazz, hasIntroductions)) { // @Aspect,类型为InstantiationModelAwarePointcutAdvisorImpl eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
代理对象的创建
代理对象的创建时机位于bean的初始化之后,因为代理对象内部还是需要去调用目标对象的方法,所以需要让目标对象实例化并完成初始化后才会创建代理对象。
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 先从缓存中获取代理对象
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 按需生成代理对象
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(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;
}
// Create proxy if we have advice.
/**
* @see AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean(java.lang.Class, java.lang.String, org.springframework.aop.TargetSource)
*/
// 获取与当前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;
}org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
protected Object createProxy(Class> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建代理工厂
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
// 进来说明proxyTargetClass=false,指定JDK代理
if (shouldProxyTargetClass(beanClass, beanName)) {
// 进来这里说明BD中有个属性preserveTargetClass=true,可以BD中属性设置的优先级最高
proxyFactory.setProxyTargetClass(true);
}
else {
// 这里会判断bean有没有实现接口,没有就只能使用CGlib
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors); // 切面
proxyFactory.setTargetSource(targetSource); // 目标对象
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 使用JDK或者CGlib创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}这里主要看JDK动态代理的实现,Proxy.newProxyInstance()的第三个参数为InvocationHandler,而这里传的是this,也就是当前的类肯定实现了InvocationHandler接口。
代理方法的执行
由于是JDK动态代理,那么代理方法的调用肯定会进入InvocationHandler.invoke()方法中,这里的InvocationHandler的实现类为org.springframework.aop.framework.JdkDynamicAopProxy。
org.springframework.aop.framework.JdkDynamicAopProxy#invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget(); // 目标对象
Class> targetClass = (target != null ? target.getClass() : null); // 目标对象的类型
// Get the interception chain for this method.
// 这里会对方法进行匹配,因为不是目标对象中的所有方法都需要增强
Listorg.springframework.aop.framework.ReflectiveMethodInvocation#proceed
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
// 执行到最后一个Advice,才会到这里执行目标方法
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
// dm.isRuntime()=true的走这
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It"s an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 走这
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
interceptorsAndDynamicMethodMatchers中第一个advice为org.springframework.aop.interceptor.ExposeInvocationInterceptor。
ExposeInvocationInterceptor#invoke
org.springframework.aop.interceptor.ExposeInvocationInterceptor#invoke
private static final ThreadLocalinvocation = new NamedThreadLocal<>("Current AOP method invocation"); public Object invoke(MethodInvocation mi) throws Throwable { MethodInvocation oldInvocation = invocation.get(); invocation.set(mi); try { return mi.proceed(); } finally { invocation.set(oldInvocation); } }
ExposeInvocationInterceptor#invoke,只干了一件事就是将MethodInvocation加入到了ThreadLocal中,这样后续可以在其他地方使用ExposeInvocationInterceptor#currentInvocation获取到MethodInvocation,而MethodInvocation中封装了目标对象,目标方法,方法参数等信息。
环绕通知的执行
org.springframework.aop.aspectj.AspectJAroundAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
JoinPointMatch jpm = getJoinPointMatch(pmi);
return invokeAdviceMethod(pjp, jpm, null, null);
}
这里会去调用环绕通知的增强方法,而环绕通知的增强方法中会执行proceedingJoinPoint.proceed(),这样就会调用下一个MethodInterceptor–>MethodBeforeAdviceInterceptor。
前置通知的执行
org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
这里又会调用MethodInvocation.proceed()传递给下一个MethodInterceptor。
后置通知的执行
org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
先执行MethodInvocation.proceed(),最后在finally块中调用后置通知的增强,不管目标方法有没有抛出异常,finally代码块中的代码都会执行,也就是不管目标方法有没有抛出异常,后置通知都会执行。
返回后通知的执行
org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
先执行MethodInvocation.proceed(),然后再执行返回后通知的增强。
异常通知的执行
org.springframework.aop.aspectj.AspectJAfterThrowingAdvice#invoke
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
先执行MethodInvocation.proceed(),如果目标方法抛出了异常就会执行异常通知的增强,然后抛出异常,所以这时返回后通知的增强就不会执行了。
总结各种通知的执行顺序:
Around begin // 环绕通知开始 Before // 前置通知 UserServiceImpl // 目标方法的执行 AfterReturning // 返回后通知 After // 后置通知 Around end // 环绕通知结束
到此这篇关于spring AOP原理及源码分析的文章就介绍到这了,更多相关spring AOP原理源码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
X 关闭
X 关闭
- 15G资费不大降!三大运营商谁提供的5G网速最快?中国信通院给出答案
- 2联想拯救者Y70发布最新预告:售价2970元起 迄今最便宜的骁龙8+旗舰
- 3亚马逊开始大规模推广掌纹支付技术 顾客可使用“挥手付”结账
- 4现代和起亚上半年出口20万辆新能源汽车同比增长30.6%
- 5如何让居民5分钟使用到各种设施?沙特“线性城市”来了
- 6AMD实现连续8个季度的增长 季度营收首次突破60亿美元利润更是翻倍
- 7转转集团发布2022年二季度手机行情报告:二手市场“飘香”
- 8充电宝100Wh等于多少毫安?铁路旅客禁止、限制携带和托运物品目录
- 9好消息!京东与腾讯续签三年战略合作协议 加强技术创新与供应链服务
- 10名创优品拟通过香港IPO全球发售4100万股 全球发售所得款项有什么用处?

