Spring AOP 从实例读源码
来源:互联网 发布:网络免费发布信息平台 编辑:程序博客网 时间:2024/05/21 15:53
Spring AOP 从实例读源码
更为完整的笔记传送门 Github
实例
LoggingAspect是一个日志切面,将所有标记了@RequestMapping的方法进行代理,在执行前、返回结果后、抛出异常后都打印相应的日志。
LoggingAspect
public class LoggingAspect { @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)") public void declareJoinPointExpression() { } @Before("declareJoinPointExpression()") public void beforeMethod(JoinPoint joinPoint) {// 连接点 Object[] args = joinPoint.getArgs();// 取得方法参数 log.info("The method [ {} ] begins with Parameters: {}", joinPoint.getSignature(), Arrays.toString(args)); } @AfterReturning(value = "declareJoinPointExpression()", returning = "result") public void afterMethodReturn(JoinPoint joinPoint, Object result) { log.info("The method [ {} ] ends with Result: {}", joinPoint.getSignature(), result); } @AfterThrowing(value = "declareJoinPointExpression()", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Exception e) { log.error("Error happened in method: [ {} ]", joinPoint.getSignature()); log.error("Parameters: {}", Arrays.toString(joinPoint.getArgs())); log.error("Exception StackTrace: {}", e); }}
HelloController
@Controllerpublic class HelloController { @RequestMapping("/hello") public ModelAndView hello(ModelAndView modelAndView){ modelAndView.addObject("user",new RegisterDTO("admin")); modelAndView.setViewName("hello"); return modelAndView; }}
约定
方法调用顺序约定
这里用 1.1) 、1.2) 来表示1)方法中的比较重要的步骤1和步骤2。
另外并不是从一开始就进行编号,而是到重要的方法时才开始编号。
public class Main { public static void main(String[] args) { ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = (UserService) applicationContext.getBean("userService"); userService.login(); }}
比如Main类中的main方法记为1),则可以将new ClassPathXmlApplicationContext记为1.1),将getBean记为1.2)。
关注点约束
我们只关注源码中的核心的业务逻辑,由于Spring过于复杂,所以哪怕只掌握其核心逻辑就很不容易了。另外文章是从实例看源码的,所以可能源码中有多条执行路径,但我们只关注实例中经过的逻辑,其他的执行路径可能会被忽略。
概念
Advisor等同于增强
AOP概述
AOP 代理可以分为两个部分:解析AOP标签和创建AOP代理。这两个部分都与IOC容器有关。如想了解AOP源码请先了解IOC源码。
1. 解析AOP标签发生在IOC的解析标签的过程,即解析自定义标签 <aop:aspectj-autoproxy />
,解析结果是在BeanFactory中注册了一个名为AnnotationAwareAspectJAutoProxyCreator的bean,用于创建AOP代理。
2. 创建AOP代理发生在IOC的createtBean中,在doCreateBean之前会先调用resolveBeforeInstantiation方法,在该方法中会调用实现了BeanPostProcessor接口的后处理的postProcessAfterInstantiation方法。
而在解析AOP标签中注册的AnnotationAwareAspectJAutoProxyCreator便实现了BeanPostProcessor接口。AnnotationAwareAspectJAutoProxyCreator会在postProcessAfterInstantiation方法中根据定义的advisor,使用JDK动态代理或CGLIB动态代理来增强bean。
前置知识
AOP术语
1、切面(aspect)
类是对物体特征的抽象,切面就是对横切关注点的抽象
2、连接点(joinpoint)
被拦截到的点,因为Spring只支持方法类型的连接点,所以在Spring中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器
3、切入点(pointcut)
对连接点进行拦截的定义
4、通知(advice)
所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、返回、环绕通知五类
5、目标对象
代理的目标对象
6、织入(weave)
将切面应用到目标对象并导致代理对象创建的过程
7、引介(introduction)
在不修改代码的前提下,引介可以在运行期为类动态地添加一些方法或字段
advisor
通知Advice是Spring提供的一种切面(Aspect)。但其功能过于简单,只能
将切面织入到目标类的所有目标方法中,无法完成将切面织入到指定目标方法中。
顾问Advisor是Spring提供的另一种切面。其可以完成更为复杂的切面织入功能。PointcutAdvisor是顾问的一种,可以指定具体 的切入点。顾问将通知进行了包装,会根据不同的通知类型,在不同的时间点,将切面织入到不同的切入点。
Advisor
public interface Advisor { Advice getAdvice(); /** * @return whether this advice is associated with a particular target instance */ boolean isPerInstance();}
PointcutAdvisor
public interface PointcutAdvisor extends Advisor { /** * Get the Pointcut that drives this advisor. */ Pointcut getPointcut();}
除了引介Advisor外,几乎所有的advisor都是PointcutAdvisor。
advice
public interface Advice {}
增强(advice)主要包括如下五种类型
1. 前置增强(BeforeAdvice):在目标方法执行前实施增强
2. 后置增强(AfterReturningAdvice):在目标方法执行后实施增强
3. 环绕增强(MethodInterceptor):在目标方法执行前后实施增强
4. 异常抛出增强(ThrowsAdvice):在目标方法抛出异常后实施增强
5. 引介增强(IntroductionIntercrptor):在目标类中添加一些新的方法和属性
JDK动态代理与CGLIB代理
JDK动态代理:
其代理对象必须是某个接口的实现,它是通过在运行时创建一个接口的实现类来完成对目标对象的代理
CGLIB代理:在运行时生成的代理对象是针对目标类扩展的子类。
CGLIB是高效的代码生产包,底层是依靠ASM操作字节码实现的,性能比JDK强。
相关标签
<aop:aspectj-autoproxy proxy-target-class=”true”/>
true表示使用CGLIB代理。
解析AOP标签
与IOC的衔接
处理自定义标签
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele);// AopNamespaceHandler NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));}
NamespaceHandlerSupport.parse
NamespaceHandlerSupport.parsepublic BeanDefinition parse(Element element, ParserContext parserContext) { return findParserForElement(element, parserContext).parse(element, parserContext);}
private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) { String localName = parserContext.getDelegate().getLocalName(element); BeanDefinitionParser parser = this.parsers.get(localName); if (parser == null) { parserContext.getReaderContext().fatal( "Cannot locate BeanDefinitionParser for element [" + localName + "]", element); } return parser;}
这里返回的parser即为AspectJAutoProxyBeanDefinitionParser。
public BeanDefinition parse(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element); extendBeanDefinition(element, parserContext); return null;}
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary
注册这个creator
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // 注册或升级AutoProxyCreator定义beanName为internalAutoProxyCreator的BeanDefinition BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement));// 对于proxy-target-class以及expose-proxy属性的增强 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);// 注册组件并通知,便于监听器做进一步处理// 其中beanDefinition的className为AnnotationAwareAspectJAutoProxyCreator registerComponentIfNecessary(beanDefinition, parserContext);}
1) AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { // 注册或升级AutoProxyCreator定义beanName为internalAutoProxyCreator的BeanDefinition BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary( parserContext.getRegistry(), parserContext.extractSource(sourceElement));// 对于proxy-target-class以及expose-proxy属性的增强 useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);// 注册组件并通知,便于监听器做进一步处理// 其中beanDefinition的className为AnnotationAwareAspectJAutoProxyCreator registerComponentIfNecessary(beanDefinition, parserContext);}
registerOrEscalateApcAsRequired
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, 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) {// 改变bean最重要的是改变bean所对应的className属性 apcDefinition.setBeanClassName(cls.getName()); } } // 如果已经存在自动代理创建器,且与将要创建的一致,那么无需再次创建 return null; } 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;}
2) useClassProxyingIfNecessary
处理proxy-target-class属性和expose-proxy属性
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) { if (sourceElement != null) { boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } }}
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE); }}
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("exposeProxy", Boolean.TRUE); }}
创建AOP代理
AbstractAutoProxyCreator.postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean;}
wrapIfNecessary
逻辑:
1)获取可以应用到该bean的所有advisor
2)创建代理
创建代理主要包含了两个步骤:
1)获取advisor
2)根据获取的advisor进行代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 如果已经处理过 if (beanName != null && this.targetSourcedBeans.contains(beanName)) { return bean; }// 无需增强 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; }// 给定的bean类是否代表一个基础设施类,基础设施类不应代理,或者配置了指定bean不需要自动代理 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // 获取适合应用到该bean的所有advisor // Create proxy if we have advice. 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) getAdvicesAndAdvisorsForBean(获取可以应用到该bean的所有advisor)
AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray();}
findEligibleAdvisors(合格的)
对于指定bean的增强方法的获取包含两个步骤:
1)获取所有的增强
2)寻找所有的增强中适用于bean的增强并应用
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;}
1.1) AbstractAdvisorAutoProxyCreator.findCandidateAdvisors(获取配置文件中的advisor)
protected List<Advisor> findCandidateAdvisors() { return this.advisorRetrievalHelper.findAdvisorBeans();}
1.1.1.1) BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans
public List<Advisor> findAdvisorBeans() { // Determine list of advisor bean names, if not cached already. String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; if (advisorNames == null) { // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let the auto-proxy creator apply to them! // 从BeanFactory中获取所有对应Advisor的类 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<Advisor>(); } List<Advisor> advisors = new LinkedList<Advisor>(); for (String name : advisorNames) { if (isEligibleBean(name)) { if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { // getBean方法可以获取Advisor advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } // Ignore: indicates a reference back to the bean we're trying to advise. // We want to find advisors other than the currently created bean itself. continue; } } throw ex; } } } } return advisors;}
1.1.2) BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors(获取标记@Aspect注解的类中的增强)
逻辑:
1)遍历所有beanName,所有在beanFactory中注册的bean都会被提取出来
2)遍历所有beanName,找出声明@Aspect注解的类,进行进一步的处理
3)对标记为AspectJ注解的类进行增强的提取
4)将提取结果加入缓存
逻辑:1)遍历所有beanName,所有在beanFactory中注册的bean都会被提取出来2)遍历所有beanName,找出声明@Aspect注解的类,进行进一步的处理3)对标记为AspectJ注解的类进行增强的提取4)将提取结果加入缓存
1.1.2.1) getAdvisors(增强器的获取)
ReflectiveAspectJAdvisorFactory.getAdvisors
逻辑:
1)对advisor的获取
2)加入同步实例化advisor以保证增强使用前的实例化
3)对DeclareParents注解的获取
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {// 获取标记为@Aspect的类 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 LinkedList<Advisor>(); for (Method method : getAdvisorMethods(aspectClass)) {// 获取普通的advisor Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), 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()) {// 如果寻找的增强器不为空,而且又配置了增强延迟初始化,那么需要在advisors开头加入同步实例化增强器 Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // 获取DeclareParents注解(引介增强IntroductionAdvisor) // Find introduction fields. for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors;}
1.1.2.1.1) getAdvisor(普通增强器的获取)
逻辑:
1)切点信息的获取
2)根据切点信息生成advisor
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);}
1.1.2.1.1.1) getPointcut(方法上切点信息的获取)
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {// 获取方法上的注解 AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } // 使用AspectJExpressionPointcut实例封装获取的信息AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);// 提取得到的注解中的表达式,如@Pointcut(“execution(* *....)”) ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); ajexp.setBeanFactory(this.beanFactory); return ajexp;}
1.1.2.1.1.1.1) findAspectJAnnotationOnMethod
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;}
获取指定方法上的注解并使用AspectJAnnotation封装
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) { A result = AnnotationUtils.findAnnotation(method, toLookFor); if (result != null) { return new AspectJAnnotation<A>(result); } else { return null; }}
1.1.2.1.2) SyntheticInstantiationAdvisor(同步实例化增强器)
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);advisors.add(0, instantiationAdvisor);
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor { public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) { super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {// 目标方法前调用,类似@Before @Override public void before(Method method, Object[] args, Object target) { // Simply instantiate the aspect// 简单初始化aspect aif.getAspectInstance(); } }); }}
1.1.2.1.3) getDeclareParentsAdvisor(获取DeclareParents注解)
DeclareParents主要用于引介增强的注解形式的实现,而其实现方式和普通增强很类似,只不过只用DeclareParentsAdvisor对功能进行封装。
private Advisor getDeclareParentsAdvisor(Field introductionField) { DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class); if (declareParents == null) { // Not an introduction field return null; } if (DeclareParents.class == declareParents.defaultImpl()) { throw new IllegalStateException("'defaultImpl' attribute must be set on DeclareParents"); } return new DeclareParentsAdvisor( introductionField.getType(), declareParents.value(), declareParents.defaultImpl());}
1.2) findAdvisorsThatCanApply(获取匹配的增强并应用)
1.1)中返回了6个advisor
buildAspectJAdvisors这个方法返回的是后3个advisor,是从LoggingAspect类中获取到的,类型是InstantiationModelAwarePointcutAdvisorImpl。
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try {// 过滤已经得到的advisor return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); }}
protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try {// 过滤已经得到的advisor return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); }}
1.2.1) canApply(真正的匹配)
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { // 处理引介增强 if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } // 处理PointcutAdvisor,是指有切入点的Advisor 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(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {// 处理引入增强 if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); }// 处理PointcutAdvisor,是指有切入点的Advisor 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; }}
过滤后最后返回的interceptors有5个。
2) createProxy(创建代理)
AbstractAutoProxyCreator.createProxy
在获取了所有对应的bean的增强后,便可以进行代理的创建了。
逻辑:
1)获取当前类中的属性
2)添加代理接口
3)封装Advisor并加入到ProxyFactory中
4)设置要代理的类
5)子类可以在此函数中进行对ProxyFactory的进一步封装
6)进行获取代理操作
specificInterceptors就是增强们(advisors)
targetSource 是new SingletonTargetSource(bean)
protected Object createProxy( Class<?> beanClass, String beanName, 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()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else {// 添加代理接口 evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) {// 加入增强 proxyFactory.addAdvisor(advisor); } // 设置要代理的类 proxyFactory.setTargetSource(targetSource);// 定制代理 customizeProxyFactory(proxyFactory); // 用来控制proxyFactory被配置后,是否还允许修改增强,缺省值为false proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader());}
2.1) buildAdvisors(封装拦截器为Advisor)
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) { // Handle prototypes correctly... Advisor[] commonInterceptors = resolveInterceptorNames(); List<Object> allInterceptors = new ArrayList<Object>(); if (specificInterceptors != null) { allInterceptors.addAll(Arrays.asList(specificInterceptors)); if (commonInterceptors.length > 0) { if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors)); } else { allInterceptors.addAll(Arrays.asList(commonInterceptors)); } } } if (logger.isDebugEnabled()) { int nrOfCommonInterceptors = commonInterceptors.length; int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0); logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + nrOfSpecificInterceptors + " specific interceptors"); } Advisor[] advisors = new Advisor[allInterceptors.size()]; for (int i = 0; i < allInterceptors.size(); i++) {// 拦截器进行封装转化为advisor advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i)); } return advisors;}
2.1.1) DefaultAdvisorAdapterRegistery.wrap
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {// 如果要封装的对象本身就是Advisor类型的,那么直接返回 if (adviceObject instanceof Advisor) { return (Advisor) adviceObject; }// 因为此封装方法只对Advisor和Advice有效,如果不是则不能封装 if (!(adviceObject instanceof Advice)) { throw new UnknownAdviceTypeException(adviceObject); } Advice advice = (Advice) adviceObject; if (advice instanceof MethodInterceptor) { // So well-known it doesn't even need an adapter.// 如果是MethodInterceptor类型则使用DefaultPointcutAdvisor封装 return new DefaultPointcutAdvisor(advice); }// 如果存在Advisor的Adapter,那么也同样需要进行封装 for (AdvisorAdapter adapter : this.adapters) { // Check that it is supported. if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice);}
2.2) getProxy
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader);}
2.2.1) createAopProxy(创建代理)
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this);}
2.2.1.1) DefaultAopProxyFactory.createAopProxy
逻辑:
如果目标对象实现了接口,默认情况下会使用JDK的动态代理
如果目标对象实现了接口,可以强制使用CGLIB(proxy-target-class=true)
如果目标对象没有实现接口,必须采用CGLIB
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() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); }}
2.2.2) getProxy(获取代理)
JdkDynamicAopProxy.getProxy
该AopProxy实现了InvocationHandler接口,重写了invoke方法。
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource()); } Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}
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 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); }// 处理hashcode 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; } // May be null. Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // 获取当前方法的拦截器链 // Get the interception chain for this method. List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); // Check whether we have any advice. If we don't, we can fallback on direct // reflective invocation of the target, and avoid creating a MethodInvocation. 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. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);// 如果没有发现任何拦截器,那么直接调用切点方法(method.invoke()) retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else {// 将拦截器封装在ReflectiveMethodInvocation // We need to create a method invocation... invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain.// proceed中实现了拦截器方法的逐一调用 retVal = invocation.proceed(); } // Massage return value if necessary. Class<?> returnType = method.getReturnType();// 返回结果 if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // Special case: it returned "this" and the return type of the method // is type-compatible. Note that we can't help if the target sets // a reference to itself in another returned object. retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } }}
2.2.2.1) ReflectiveMethodInvocation.proceed(执行拦截器链的方法)
public Object proceed() throws Throwable {// 执行完所有增强后,执行切点方法(method.invoke()) // We start with an index of -1 and increment early. if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { 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. InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; if (dm.methodMatcher.matches(this.method, this.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); }}
2.2.2.1.1) invokeJoinpoint(执行切点方法)
protected Object invokeJoinpoint() throws Throwable { 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); }}
2.2.2.1.2) invoke (执行拦截器方法)
public interface MethodInterceptor extends Interceptor { Object invoke(MethodInvocation invocation) throws Throwable;}
CglibAopProxy.getProxy
虽然返回的Proxy是ObjenesisCglibAopProxy,但它继承了CglibAopProxy 的getProxy方法。
实现了Enhancer的创建及接口封装。
public Object getProxy(ClassLoader classLoader) { if (logger.isDebugEnabled()) { logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource()); } try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy"); Class<?> proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) { proxySuperClass = rootClass.getSuperclass(); Class<?>[] additionalInterfaces = rootClass.getInterfaces(); for (Class<?> additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface); } } // 验证class // Validate the class, writing log messages as necessary. validateClassIfNecessary(proxySuperClass, classLoader); // 创建及配置Enhancer // Configure CGLIB Enhancer... Enhancer enhancer = createEnhancer(); if (classLoader != null) { enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader && ((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) { enhancer.setUseCache(false); } } enhancer.setSuperclass(proxySuperClass); enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised)); enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE); enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader)); // 设置拦截器 Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = new Class<?>[callbacks.length]; for (int x = 0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types); // 生成代理类以及创建代理 // Generate the proxy class and create a proxy instance. return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (IllegalArgumentException ex) { throw new AopConfigException("Could not generate CGLIB subclass of class [" + this.advised.getTargetClass() + "]: " + "Common causes of this problem include using a final class or a non-visible class", ex); } catch (Throwable ex) { // TargetSource.getTarget() failed throw new AopConfigException("Unexpected AOP exception", ex); }}
2.2.2.1) getCallbacks
private Callback[] getCallbacks(Class<?> rootClass) throws Exception { // Parameters used for optimisation choices... boolean exposeProxy = this.advised.isExposeProxy(); boolean isFrozen = this.advised.isFrozen(); boolean isStatic = this.advised.getTargetSource().isStatic(); // Choose an "aop" interceptor (used for AOP calls).// 将拦截器封装在DynamicAdvisedInterceptor中 Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised); // Choose a "straight to target" interceptor. (used for calls that are // unadvised but can return this). May be required to expose the proxy. Callback targetInterceptor; if (exposeProxy) { targetInterceptor = isStatic ? new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()); } else { targetInterceptor = isStatic ? new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : new DynamicUnadvisedInterceptor(this.advised.getTargetSource()); } // Choose a "direct to target" dispatcher (used for // unadvised calls to static targets that cannot return this). Callback targetDispatcher = isStatic ? new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp(); Callback[] mainCallbacks = new Callback[] {// 将拦截器链加入到Callback中 aopInterceptor, // for normal advice targetInterceptor, // invoke target without considering advice, if optimized new SerializableNoOp(), // no override for methods mapped to this targetDispatcher, this.advisedDispatcher, new EqualsInterceptor(this.advised), new HashCodeInterceptor(this.advised) }; Callback[] callbacks; // If the target is a static one and the advice chain is frozen, // then we can make some optimisations by sending the AOP calls // direct to the target using the fixed chain for that method. if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = new Callback[methods.length]; this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length); // TODO: small memory optimisation here (can skip creation for methods with no advice) for (int x = 0; x < methods.length; x++) { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = new FixedChainStaticTargetInterceptor( chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); this.fixedInterceptorMap.put(methods[x].toString(), x); } // Now copy both the callbacks from mainCallbacks // and fixedCallbacks into the callbacks array. callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length]; System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); this.fixedInterceptorOffset = mainCallbacks.length; } else { callbacks = mainCallbacks; } return callbacks;}
CGLIB对于方法的拦截是通过将自定义的拦截器(实现了MethodInterceptor接口)加入Callback中并在调用代理时直接激活拦截器的intercept方法实现的,那么在getCallback中实现了这样一个目的:DynamicAdvisedInterceptor继承自MethodInterceptor,加入到Callback中后,在再次调用代理时会直接调用DynamicAdvisedInterceptor中的intercept方法。
CGLIB方式实现的代理,其核心逻辑在DynamicAdvisedInterceptor中的intercept方法中(JDK动态代理的核心逻辑是在invoke方法中)。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable { private final AdvisedSupport advised; public DynamicAdvisedInterceptor(AdvisedSupport advised) { this.advised = advised; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object oldProxy = null; boolean setProxyContext = false; Class<?> targetClass = null; Object target = null; try { if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // May be null. Get as late as possible to minimize the time we // "own" the target, in case it comes from a pool... target = getTarget(); if (target != null) { targetClass = target.getClass(); }// 获取拦截器链 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; // Check whether we only have one InvokerInterceptor: that is, // no real advice, but just reflective invocation of the target. if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { // 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. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);// 如果拦截器为空,则直接激活原方法 retVal = methodProxy.invoke(target, argsToUse); } else {// 进入拦截器链 // We need to create a method invocation... retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null) { releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } } @Override public boolean equals(Object other) { return (this == other || (other instanceof DynamicAdvisedInterceptor && this.advised.equals(((DynamicAdvisedInterceptor) other).advised))); } /** * CGLIB uses this to drive proxy creation. */ @Override public int hashCode() { return this.advised.hashCode(); } protected Object getTarget() throws Exception { return this.advised.getTargetSource().getTarget(); } protected void releaseTarget(Object target) throws Exception { this.advised.getTargetSource().releaseTarget(target); }}
2.2.2.2) createProxyClassAndInstance
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) { Class<?> proxyClass = enhancer.createClass(); Object proxyInstance = null; if (objenesis.isWorthTrying()) { try { proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache()); } catch (Throwable ex) { logger.debug("Unable to instantiate proxy using Objenesis, " + "falling back to regular proxy construction", ex); } } if (proxyInstance == null) { // Regular instantiation via default constructor... try { proxyInstance = (this.constructorArgs != null ? proxyClass.getConstructor(this.constructorArgTypes).newInstance(this.constructorArgs) : proxyClass.newInstance()); } catch (Throwable ex) { throw new AopConfigException("Unable to instantiate proxy using Objenesis, " + "and regular proxy instantiation via default constructor fails as well", ex); } } ((Factory) proxyInstance).setCallbacks(callbacks); return proxyInstance;}
如果配置了proxy-target-class=true,那么会使用CGLIB代理;这里没有配置,默认使用的是JDK的动态代理。
总结
有两张顺序图简单地解释了上述源码,图源网络,侵删。
解析AOP标签
创建AOP代理
个人总结
AOP始于注解定义的Aspect切面类和XML中中的aspectj-autoproxy标签,终于JDK动态代理或CGLIB动态代理。本质上就是读入增强器advisor,对符合adivisor的pointcut的方法进行代理,增强advisor提供的功能。
- Spring AOP 从实例读源码
- Spring IOC 从实例读源码
- Spring Transaction 从实例读源码
- Spring MVC 从实例读源码
- Spring 从实例读源码系列
- Spring AOP 入门实例
- Spring AOP 入门实例
- Spring AOP实例
- Spring AOP 实例
- Spring aop使用实例
- Spring AOP 简单实例
- spring aop 简单实例
- Spring 2.5 AOP 实例
- Spring AOP 实例
- spring AOP 入门实例
- Spring的AOP实例
- Spring Aop实例
- Spring之AOP实例
- java核心基础--jdk源码分析学习--TreeMap
- 面向对象程序设计上机练习十一(运算符重载)
- TensorFlow实战(二)自编码器
- binary tree traversal
- 对面向对象的编程模式的理解
- Spring AOP 从实例读源码
- 二分法以及牛顿法开根号
- 图的存储c++实现
- JSP&Servlet学习笔记(1): Web应用程序简介
- java单例模式
- sql语句练习50题(Mysql版)
- EF中的那些批量操作
- IT与风投
- 线数目