Spring Framework Aop原理
原因
Spring Framework 提供了除IOC之外的很多有意思的性能,深入研究其技术原理,可在我的项目技术选型上提供更多的思路和技术把控。Spring Framewrok 代码由大佬精心打磨,能够从性能实现上学习和模拟。另外Spring Framework是Java我的项目开发的根底,其余技术框架都会基于或者与Spring 兼容,钻研其中的技术原理,可疾速把握其余技术框架的技术原理,比方 Spring boot \ Spring cloud...
简述
Spring Framework 呈现的背景是,Java 对象之间调用关系简单,为简化对象调用,Spring Framework 基于Dependency Injection,将对象的控制权转移到BeanFactory,由框架负责对象的生命周期,将对象与Bean进行映射,Bean的生命周期由欠缺的管理机制。
Aop切面编程是区别于面向对象编程的,Spring Framework也提供了实现,成为 Spring's Aop,仅反对办法级别的切面编程,属于运行期织入,赫赫有名的Aspectj,属于更高级的一种框架,可能反对到结构器、办法、属性级别。
前提
Spring Framework 推出的Aop性能是基于Ioc实现的。须要对IOC的技术原理有肯定的理解,另外对切面编程的根底有个根本的理解。
注释
利用
maven pom dependency
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.20</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> </dependency>
Application 我的项目EntryPoint
@ComponentScan@Configuration// 开启Aspectj注解反对@EnableAspectJAutoProxypublic class Application { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class); ServiceB serviceB = context.getBean("serviceB", ServiceB.class); serviceB.say(); }}
切面逻辑
@Aspect@Componentpublic class AopTest { @Pointcut("execution(* org.example.circularReference.*.*(..))") public void pointCut() { } @Around("pointCut()") public Object doAround(ProceedingJoinPoint pjp) throws Throwable { System.out.println("AopTest ... "); return pjp.proceed(); }}
代码逻辑
@Servicepublic class ServiceB { public void say() { System.out.println("Application say ..."); }}
@EnableAspectJAutoProxy
- 可能反对解决@Aspect标注的Component。
- 搭配@Configuration 注解一起应用。
- 设置属性 proxyTargetClass=true,仅用Cglib生成代理,接口或者对象代理,接口的默认代理实现是JDK proxy.
- 须要引入 aspectjweaver。
- 通过 @Import 注解引入 AspectJAutoProxyRegistrar。
AspectJAutoProxyRegistrar
注册AnnotationAwareAspectJAutoProxyCreator 到BeanDefinitionRegistry当中。
具体代码在:AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry)
RootBeanDefinition beanDefinition = new RootBeanDefinition(AnnotationAwareAspectJAutoProxyCreator.class); 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;
AnnotationAwareAspectJAutoProxyCreator
解决利用上下文所有AspectJ注解的aspects \ Spring Advisors,解决逻辑在 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
.
任何设置AspectJ注解的类都将被自动识别,Spring AOP的基于代理的model、办法连接点能够依照规定匹配。
通过UML图,creator 实现了 SmartInstantiationAwareBeanPostProcessor
接口,在 AbstractAutoProxyCreator
抽象类中实现了 postProcessBeforeInstantiation
postProcessAfterInitialization
办法,将Spring Aop 性能实现参加到 Bean 创立的过程中,将Bean的信息进行反射,取得Class信息与Advisor进行匹配,生成对应的代理类。
postProcessBeforeInstantiation 解决customeTargetSource。
postProcessAfterInitialization 解决实例化后的Bean,匹配Pointcut。
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (this.earlyProxyReferences.remove(cacheKey) != bean) { // 通过晚期代理的查看后,开始执行真正的aop逻辑 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } 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. getAdvicesAndAdvisorsForBean 会是一个精彩的逻辑。 // 查找能够匹配的所有Advisor 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; }
上述局部是由Aop实现一个大抵逻辑。上面将会介绍Aop的具体工作原理。
getAdvicesAndAdvisorsForBean
查找能够匹配的所有Advisor。具体实现在 org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator
。
protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { // 要害逻辑会在findEligibleAdvisors中连续。 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
@Override protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { // 要害逻辑将在buildAspectJAdvisors()中连续。 advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; }
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
将Spring Beanfactory中@Aspect注解润饰的类转换为Spring Advisors.
- 获取所有的BeanDefinition汇合
- 获取 Class 对象
- 判断类上是否有Aspect注解
- 获取类上的所有Advisor.
public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new ArrayList<>(); aspectNames = new ArrayList<>(); String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); // 1.获取所有的BeanDefinition汇合 for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. // 2.获取 Class 对象 Class<?> beanType = this.beanFactory.getType(beanName, false); if (beanType == null) { continue; } // 3.判断是否有Aspect注解 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { // 4.获取类上的所有Advisor. MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } List<Advisor> advisors = new ArrayList<>(); for (String aspectName : aspectNames) { List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { advisors.addAll(cachedAdvisors); } else { MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } return advisors; }
解析Aspect注解获取Advisor的要害代码:
MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
advisorFactory:AspectJAdvisorFactory -> AbstractAspectJAdvisorFactory -> ReflectiveAspectJAdvisorFactory
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory
应用反射技术解析@Aspect润饰的类。
@Override public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new ArrayList<>(); // 重点关注 getAdvisorMethods for (Method method : getAdvisorMethods(aspectClass)) { // Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect // to getAdvisor(...) to represent the "current position" in the declared methods list. // However, since Java 7 the "current position" is not valid since the JDK no longer // returns declared methods in the order in which they are declared in the source code. // Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods // discovered via reflection in order to support reliable advice ordering across JVM launches. // Specifically, a value of 0 aligns with the default value used in // AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor). // 重点关注 如何将解析后method转换为 advisor Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName); if (advisor != null) { advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // Find introduction fields. for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; } private List<Method> getAdvisorMethods(Class<?> aspectClass) { List<Method> methods = new ArrayList<>(); // 解析@Aspect润饰的类,获取其中Advisor相干的办法。 ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter); if (methods.size() > 1) { methods.sort(adviceMethodComparator); } return methods; } public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); } private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]); ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); if (this.beanFactory != null) { ajexp.setBeanFactory(this.beanFactory); } return ajexp; } // AspectJExpressionPointcut
BeanFactoryAspectInstanceFactory
org.springframework.aop.aspectj.AspectInstanceFactory
接口的实现。
若应用原型模式,会被实例化屡次,可能失去不正确的语义,能够应用 LazySingletonAspectInstanceFactoryDecorator 来装璜类,达到只实例化一次的成果。
InstantiationModelAwarePointcutAdvisorImpl
AspectJPointcutAdvisor的外部实现,@Aspect 批改的类中的每个办法都是一个advisor,也会只有一个实例就是此类。
AspectJExpressionPointcut
org.springframework.aop.Pointcut
接口的外部实现。应用Aspectj技术计算 pointcut 表达式(aspect表达式),表达式最初还是由Spring aop model 解决,只能反对到method级别。
以上是Spring Advisor 造成的过程。上面开始执行advisor匹配的过程。
// AbstractAdvisorAutoProxyCreator protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { // 转移到 AopUtils 中 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } }
// AopUtils public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new ArrayList<>(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } // 转移办法 if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; }
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; // 执行重载办法的逻辑 return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } }
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(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } Set<Class<?>> classes = new LinkedHashSet<>(); if (!Proxy.isProxyClass(targetClass)) { classes.add(ClassUtils.getUserClass(targetClass)); } classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); for (Class<?> clazz : classes) { Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { if (introductionAwareMethodMatcher != null ? // 真正执行匹配的逻辑 introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) : methodMatcher.matches(method, targetClass)) { return true; } } } return false; }
// AspectJExpressionPointcut // 具体匹配逻辑在 aspectj 中,有趣味的能够深入研究下。 @Override public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) { obtainPointcutExpression(); ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass); // Special handling for this, target, @this, @target, @annotation // in Spring - we can optimize since we know we have exactly this class, // and there will never be matching subclass at runtime. if (shadowMatch.alwaysMatches()) { return true; } else if (shadowMatch.neverMatches()) { return false; } else { // the maybe case if (hasIntroductions) { return true; } // A match test returned maybe - if there are any subtype sensitive variables // involved in the test (this, target, at_this, at_target, at_annotation) then // we say this is not a match as in Spring there will never be a different // runtime subtype. RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch); return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass)); } }
以上是 Spring Advisor 匹配的过程。
创立代理的局部就不做解释了。
以上就是Spring Aop 技术的原理。通读后可对Aop实现有个大抵的了解,Spring 借助 AspectJ 的注解和表达式匹配,实现Spring Aop 的根底性能,同时又和Spring Ioc 进行交融。