当前位置: 首页 > news >正文

鄂温克族网站建设/北京网站优化排名

鄂温克族网站建设,北京网站优化排名,成都网站维护多少钱,网站建设插入竖线文章目录AOP原理解析简单案例源码分析EnableAspectJAutoProxy注解AspectJAutoProxyRegistrarAnnotationAwareAspectJAutoProxyCreator实现了BeanFactoryAware接口实现InstantiationAwareBeanPostProcessor接口创建代理对象分析包装代理对象是否适合被包装什么是基础class解析As…

文章目录

  • AOP原理解析
    • 简单案例
    • 源码分析
      • @EnableAspectJAutoProxy注解
        • AspectJAutoProxyRegistrar
        • AnnotationAwareAspectJAutoProxyCreator
          • 实现了BeanFactoryAware接口
          • 实现InstantiationAwareBeanPostProcessor接口
    • 创建代理对象分析
      • 包装代理对象
        • 是否适合被包装
          • 什么是基础class
        • 解析@Aspect注解标注的类获取增强器
          • 找到候选的增强器
        • 获取能够使用的增强器
      • 创建代理对象
    • 代理对象调用目标方法
      • 调用原理
      • 演示
      • 代理对象调用原理分析
        • 调用代理对象
        • 把增强器转为方法拦截器链
    • 总结

AOP原理解析

简单案例

  • 一个用于计算的接口
public interface Calculate {int add(int numa, int numb);int reduce(int numa, int numb);int div(int numa, int numb);int multi(int numa, int numb);
}
  • 实现类
public class SimpleCalculate implements Calculate {@Overridepublic int add(int numa, int numb) {return numa + numb;}@Overridepublic int reduce(int numa, int numb) {return numa - numb;}@Overridepublic int div(int numa, int numb) {return numa / numb;}@Overridepublic int multi(int numa, int numb) {return numa * numb;}
}
  • 对这个类进行aop编程的切面
@Aspect
public class LogAspect {@Pointcut("execution(* org.apdoer.spring.aop.SimpleCalculate.*(..))")public void pointcut(){}@Before(value = "pointcut()")public void beforeAdvice(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("执行目标方法=="+methodName+"之前执行前置通知,参数"+ Arrays.asList(joinPoint.getArgs()));}@After(value = "pointcut()")public void afterAdvice(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("执行目标方法=="+methodName+"之后执行后置通知,参数"+ Arrays.asList(joinPoint.getArgs()));}@AfterReturning(value = "pointcut()")public void returningAdvice(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("执行目标方法=="+methodName+"之前执行返回通知,参数"+ Arrays.asList(joinPoint.getArgs()));}@AfterThrowing(value = "pointcut()")public void afterThrowingAdvice(JoinPoint joinPoint){String methodName = joinPoint.getSignature().getName();System.out.println("执行目标方法=="+methodName+"之前执行异常通知,参数"+ Arrays.asList(joinPoint.getArgs()));}
}

需要注意的是aspect不是spring的包,需要引入如下依赖

        <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
  • 配置类
@Configuration
@EnableAspectJAutoProxy
public class TestAopConfig {@Beanpublic Calculate calculate() {return new SimpleCalculate();}@Beanpublic LogAspect logAspect() {return new LogAspect();}
}
  • 测试类
public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TestAopConfig.class);Calculate calculate = (Calculate) applicationContext.getBean("calculate");System.out.println(calculate.add(1, 2));}
}

这里就不一一测试了

源码分析

刚才可以看到在配置类上加了一个@EnableAspectJAutoProxy注解,这个注解是干什么用的

@EnableAspectJAutoProxy注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {boolean proxyTargetClass() default false;boolean exposeProxy() default false;
}
  1. 这个类上有个@Import注解,这个注解可以给容器中添加组件
  2. 这个注解有两个属性值
    • proxyTargetClass:用于配置代理的方式,true代表使用cglib代替jdk的动态代理
    • exposeProxy:是否将代理对象通过ThreadLocal暴露到aop上下文缓存中,如果暴露,我们可以在上下文中直接获取到,这里可以用来解决同类调用aop不生效的问题
  3. springboot也是这个原理,不过是通过SPI机制自动装配,所以只要有了Aspectj的依赖就可以

AspectJAutoProxyRegistrar

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {//向容器中注册对应的aspectj注解自动代理创建器AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);AnnotationAttributes enableAspectJAutoProxy =AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);if (enableAspectJAutoProxy != null) {if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}
}

AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar

向我们的容器中注册了一个AnnotationAwareAspectJAutoProxyCreator

注册beanDefinition就没必要点进去看了,具体在AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);这一行代码中

重点是AnnotationAwareAspectJAutoProxyCreator这个代理创建器是什么

AnnotationAwareAspectJAutoProxyCreator

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-deS79qBb-1618931902808)(E44F701E638E41FBA3C0E67DCAADEAC8)]

以上是这个代理创建器的类图,有几点值得关注

  1. 实现了BeanFactoryAware接口,可以将BeanFactory绑定到组件上,通过beanFactory获取容器内的bean
  2. 还实现了InstantiationAwareBeanPostProcessor接口,也是一种后置处理器,可以在bean实例化前后执行一些操作

下面分别说明各自的作用

实现了BeanFactoryAware接口

AbstractAdvisorAutoProxyCreator覆盖了AbstractAutoProxyCreatorsetBeanFactory方法做了两件事

  1. 调用父类的setBeanFactory方法
  2. 调用initBeanFactory初始化BeanFactory,但是被子类覆盖,最终调用如下
	@Overrideprotected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {super.initBeanFactory(beanFactory);//若 apsectj的增强器工厂对象为空,我们就创建一个ReflectiveAspectJAdvisorFactoryif (this.aspectJAdvisorFactory == null) {this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);}//不为空 我们就把aspectJAdvisorFactory 包装为BeanFactoryAspectJAdvisorsBuilderAdapterthis.aspectJAdvisorsBuilder =new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);}

所以, 实现BeanFactoryAware接口的作用就是

  1. BeanFactory绑定到照这个AnnotationAwareAspectJAutoProxyCreator组件上
  2. AnnotationAwareAspectJAutoProxyCreatoraspectJAdvisorsBuilder赋值
  3. 能够通过beanFactory拿到增强器
实现InstantiationAwareBeanPostProcessor接口
  1. bean初始化之前
	@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {Object cacheKey = getCacheKey(beanClass, beanName);// Create proxy here if we have a custom TargetSource.// Suppresses unnecessary default instantiation of the target bean:// The TargetSource will handle target instances in a custom fashion.TargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {if (StringUtils.hasLength(beanName)) {this.targetSourcedBeans.add(beanName);}Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}return null;}

这里面的逻辑如下

  • 判断缓存中是否包含当前bean,如果不包含,继续判断是否是已经代理的bean
    • 代理过,不处理
    • 没代理过,判断当前bean是否是系统bean,或者是切面逻辑不会包含的bean,如果是缓存起来
  • 经过这一步处理后, 只有在targetSource中没有进行缓存,并且应该被切面逻辑包含,但是还未生成代理对象的bean才会通过此方法
  1. bean初始化之后
	@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.remove(cacheKey) != bean) {//如果当前的对象适合被包装称为代理bean就进行处理return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}

上面的wrapIfNecessary包装bean就是真正的创建代理对象逻辑

创建代理对象分析

包装代理对象

是否适合被包装

前面说到会判断是否适合被包装成为代理bean,那么是怎么判断呢

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {//1.已经处理的不再处理if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}//2.不需要被增强的直接返回if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}//3.判断当前bean是不是基础类型的bean,或者指定类型的bean 不需要代理if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// 4.如果有增强器,创建代理对象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. 已经处理的不再处理
  2. 不需要被增强的直接返回
  3. 判断当前bean是不是基础类型的bean,或者指定类型的bean 不需要代理
  4. 如果有增强器,创建代理对象
什么是基础class

前面判断是否适合被包装提到基础对象

	protected boolean isInfrastructureClass(Class<?> beanClass) {boolean retVal = Advice.class.isAssignableFrom(beanClass) ||Pointcut.class.isAssignableFrom(beanClass) ||Advisor.class.isAssignableFrom(beanClass) ||AopInfrastructureBean.class.isAssignableFrom(beanClass);if (retVal && logger.isTraceEnabled()) {logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");}return retVal;}

其实就是判断当前的class是不是 Pointcut Advisor Advice AopInfrastructureBean 其中的一种

解析@Aspect注解标注的类获取增强器

	@Override@Nullableprotected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {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;}

这里面包含几步

  • 找到候选的增强器
  • 找到可以使用的增强器
找到候选的增强器
	@Overrideprotected 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) {advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());}return advisors;}

这段代码做了两件事

  • ioc容器中获取所有增强器
  • beanfactory中给所有aspectj切面配置增强器
  1. 从ioc容器中获取所有增强器
public List<Advisor> findAdvisorBeans() {//1.先从缓存中获取增强器   cachedAdvisorBeanNames是advisor的名称String[] 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!advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);this.cachedAdvisorBeanNames = advisorNames;}if (advisorNames.length == 0) {return new ArrayList<>();}List<Advisor> advisors = new ArrayList<>();for (String name : advisorNames) {if (isEligibleBean(name)) {//忽略正在创建的增强器if (this.beanFactory.isCurrentlyInCreation(name)) {if (logger.isTraceEnabled()) {logger.trace("Skipping currently created advisor '" + name + "'");}}else {try {//通过getBean的形式创建增强器 //并且将bean 添加到advisors中advisors.add(this.beanFactory.getBean(name, Advisor.class));}}}}return advisors;}

这段代码的逻辑很简单,如注释

  1. beanfactory中所有的aspectj切面配置增强器
	public List<Advisor> buildAspectJAdvisors() {//1.先从缓存中获取增强器对象List<String> aspectNames = this.aspectBeanNames;//缓存中没有获取到if (aspectNames == null) {synchronized (this) {//在尝试从缓存中获取一次aspectNames = this.aspectBeanNames;//还是没有获取到if (aspectNames == null) {//2.从容器中获取所有的bean的name List<Advisor> advisors = new LinkedList<Advisor>();aspectNames = new LinkedList<String>();String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);//2.遍历beanNames	,检查对应的bean是否包含有Aspect注解	for (String beanName : beanNames) {if (!isEligibleBean(beanName)) {continue;}//根据beanName获取bean的类型Class<?> beanType = this.beanFactory.getType(beanName);if (beanType == null) {continue;}//检查beanType是否包含Aspectif (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);//创建一个Aspect类的源信息对象AspectMetadata amd = new AspectMetadata(beanType, beanName);if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);//3.从aspectj切面中获取通知器,即我们配置的前置通知,后置通知...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;}}}//缓存中有增强器,我们从缓存中获取返回出去List<Advisor> advisors = new LinkedList<Advisor>();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注解,获取增强器

  • 先从缓存中获取增强器对象
  • 如果缓存没有,就获取容器中所有的beanname,依次判断对应的bean是否是一个被@Aspect注解标注的类
  • 如果是,调用advisorFactory.getAdvisors获取通知器

至于通过被@Aspect注解标注的类来获取通知器,也可以稍微看一下

@Overridepublic List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {//1.获取标识了@Aspect注解的切面类Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();//2.获取切面的名称String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();//3.验证切面类validate(aspectClass);...List<Advisor> advisors = new ArrayList<>();//4.获取切面类中除开@PointCut注解标注的其他所有方法for (Method method : getAdvisorMethods(aspectClass)) {//5.给每个方法获取增强Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);if (advisor != null) {advisors.add(advisor);}}...return advisors;}

这段代码的意思就是

  • 获取切面类
  • 为切面类中除开@PointCut注解标记的其他所有方法获取增强

那么是怎么为方法获取增强的呢

	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,int declarationOrderInAspect, String aspectName) {//1.获取切点表达式AspectJExpressionPointcut expressionPointcut = getPointcut(candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());if (expressionPointcut == null) {return null;}//2.创建增强实现类return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,this, aspectInstanceFactory, declarationOrderInAspect, aspectName);}

再看看切点表达式的获取

	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {//1.获取切面注解 @Before @After...AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);if (aspectJAnnotation == null) {return null;}//2.获取切点表达式对象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;}

切面注解的获取,不用看都能猜得到,就看方法是是否有那几个注解呗

	protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {// ASPECTJ_ANNOTATION_CLASSES就是 {Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class}for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);if (foundAnnotation != null) {return foundAnnotation;}}return null;}

再回到前面的为方法获取增强,获取切点表达式后的创建增强实现类

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {...if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {...}else {// A singleton aspect.this.pointcut = this.declaredPointcut;this.lazy = false;//实例化切面this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);}}

这一步把切点,候选的方法…统一处理生成一个增强器

实例化切面是怎么做的

	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {//1.获取候选切面Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();//2.获取切面注解AspectJAnnotation<?> aspectJAnnotation =AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);...AbstractAspectJAdvice springAdvice;//3.判断注解类型switch (aspectJAnnotation.getAnnotationType()) {//3.1如果是切点,返回nullcase AtPointcut:if (logger.isDebugEnabled()) {logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");}return null;//3.2 环绕通知case AtAround:springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;//3.3 前置通知case AtBefore:springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;//3.4后置通知case AtAfter:springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);break;//3.5返回通知case AtAfterReturning:springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterReturningAnnotation.returning())) {springAdvice.setReturningName(afterReturningAnnotation.returning());}break;//3.6异常通知case AtAfterThrowing:springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {springAdvice.setThrowingName(afterThrowingAnnotation.throwing());}break;default:throw new UnsupportedOperationException("Unsupported advice type on method: " + candidateAdviceMethod);}// Now to configure the advice...springAdvice.setAspectName(aspectName);springAdvice.setDeclarationOrder(declarationOrder);//4.获取方法的参数列表,设置到切面方法上去String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);if (argNames != null) {springAdvice.setArgumentNamesFromStringArray(argNames);}springAdvice.calculateArgumentBindings();return springAdvice;}

获取能够使用的增强器

	protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}}

调用到AopUtils.findAdvisorsThatCanApply

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {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 processedcontinue;}if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}

找的逻辑相对简单,怎么判断这个canApply

	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;}}

还调用了一个canApply

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {//1.创建方法匹配器MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}//2.包装方法匹配器IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}//3.获取类和接口Set<Class<?>> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));//4.获取每个类对应的所有方法进行匹配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;}

创建代理对象

	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {//1.判断容器类型if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}//2.创建代理工厂ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);//3.配置代理方式.默认是false.jdk动态代理if (!proxyFactory.isProxyTargetClass()) {if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);}else {//检查beanclass是否实现了接口,未实现接口,为trueevaluateProxyInterfaces(beanClass, proxyFactory);}}//4.获取容器中的方法增强器Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}//5.创建代理对象return proxyFactory.getProxy(getProxyClassLoader());}

到了真正的创建代理对象了

	@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (!IN_NATIVE_IMAGE &&(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.");}//实现了接口,用jdk动态代理if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}

在没有显示配置的情况下,如果实现了接口,则使用jdk动态代理

	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);//创建jdk代理对象return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);}

创建代理对象的流程

  1. 判断容器类型
  2. 获取代理工厂
  3. 设置代理方式
  4. 获取容器中的方法增强
  5. 创建代理对象

代理对象调用目标方法

调用原理

当我们在一个类中调用同类注解方法,获取其他方法,默认是采用本类对象调用,所有注解都会失效.

@EnableAspectJAutoProxy(exposeProxy = true)这个表示是否暴露代理对象

如果配置了为true,代理对象将会被放到线程变量中,通过aop上下文可以获取到进行调用

int retVal = ((Calculate) AopContext.currentProxy()).add(numa,numb);

演示

在前面的实现类中新增方法

    public int mod(int numa,int numb){int retVal = ((Calculate) AopContext.currentProxy()).add(numa,numb);//int retVal = this.add(numa,numb);return retVal%numa;}

代理对象调用原理分析

调用代理对象

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 {Object retVal;//1.是否暴露代理对象if (this.advised.exposeProxy) {// 把代理 对象放到ThreadLocal中oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}//2.获取被代理对象target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);// 3.获取方法拦截器链(把增强器转换成方法拦截器链)List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);//4.如果没有方法拦截器链,通过反射直接调用if (chain.isEmpty()) {Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);}else {// We need to create a method invocation...MethodInvocation invocation =new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// 把方法调用放到方法拦截器链中retVal = invocation.proceed();}// 处理返回类型Class<?> returnType = method.getReturnType();if (retVal != null && retVal == target &&returnType != Object.class && returnType.isInstance(proxy) &&!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {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 {...}}

调用代理对象的逻辑

  1. 获取代理对象,设置是否需要暴露代理对象
  2. 获取方法拦截器链,创建方法调用执行(有缓存)
  3. 处理返回类型

把增强器转为方法拦截器链

	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {//1.从缓存中获取,第一次肯定没有MethodCacheKey cacheKey = new MethodCacheKey(method);List<Object> cached = this.methodCache.get(cacheKey);if (cached == null) {//2.获取所有的拦截器cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);//3.放入缓存this.methodCache.put(cacheKey, cached);}return cached;}

真正的获取拦截器链

	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {List<Object> interceptorList = new ArrayList<>(advisors.length);Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());Boolean hasIntroductions = null;//遍历所有增强器集合for (Advisor advisor : advisors) {//判断增强器是不是PointcutAdvisorif (advisor instanceof PointcutAdvisor) {PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;//通过方法匹配器进行匹配if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();boolean match;if (mm instanceof IntroductionAwareMethodMatcher) {if (hasIntroductions == null) {hasIntroductions = hasMatchingIntroductions(advisors, actualClass);}match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);}else {match = mm.matches(method, actualClass);}//匹配到,就把增强器转换成拦截器链if (match) {MethodInterceptor[] interceptors = registry.getInterceptors(advisor);if (mm.isRuntime()) {for (MethodInterceptor interceptor : interceptors) {interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));}}else {interceptorList.addAll(Arrays.asList(interceptors));}}}}...}return interceptorList;}

获取方法拦截器链的逻辑

  1. 获取所有的增强器
  2. 通过方法匹配器遍历匹配,如果匹配到,就把增强器转换成拦截器链

总结

  1. @EnableAspectJAutoProxy注解通过ImportBeanDefinitionRegistrar的方式向容器中注册了AspectJAutoProxyRegistrar组件
  2. 这个组件实现了BeanPostProcessor接口,作为一个bean的后置处理器,能在bean的实例化前后处理一些工作
  3. bean实例化之后,会去判断当前是不是 Pointcut Advisor Advice AopInfrastructureBean 其中的一种,即不需要代理的对象
  4. 解析被@Aspect注解标注的类,获取可用的增强器
  5. 有增强器就去创建代理对象
  6. 调用的时候,获取被代理对象的方法,把增强器转换成方法拦截器链,把方法调用放到方法拦截器链中,从而达到面向切面编程
http://www.lbrq.cn/news/1404343.html

相关文章:

  • 做的网站程序防止倒卖/优化大师软件下载
  • 那家做网站好/关联词有哪些五年级
  • 青岛做公司网站的公司/沈阳网络关键词排名
  • 超频三网站谁家做的/关键词投放
  • 做网站有啥软件/口红的推广软文
  • 网站字体样式/网站数据分析
  • 网站怎么做响应式/品牌推广公司
  • 手机网站底部导航代码/宝塔建站系统
  • 天津个人做网站/全面网络推广营销策划
  • 上饶做网站要多少钱/知名品牌营销策划案例
  • 国家工程建设标准化协会网站/郑州优化网站关键词
  • 有趣的网站网址/搜索引擎优化工作
  • 什么网站能免费/免费企业建站
  • 彩票网站开发软件/网络销售怎么学
  • 爱站网关键词挖掘工具站长工具/什么软件推广效果好
  • mac可以做网站服务器吗/南京 seo 价格
  • 做安全平台网站/南宁网站建设优化服务
  • 免费网站安全软件大全免费下载安装/海外推广专员
  • 网站建设推广有没有/网络推广人员
  • 团购网站营销方案/快速优化排名公司推荐
  • 中国网站排名站长之家/crm客户管理系统
  • dede织梦php文章图片网站源码 完整后台 带在线音乐/优化大师电脑版官网
  • 网站受到攻击 怎么做/广东seo加盟
  • 外贸网站建设报价差别那么大花钱多吃亏/太原自动seo
  • 什么网站广告做多/搜索关键词排名优化技术
  • 东莞企创做网站怎么样/交易平台
  • 多钱网网站/seo月薪
  • 怎么样再自己的网站做二级域名/上海最近三天的新闻
  • 宜昌 公司 网站建设/2021年重大新闻事件
  • 湖南平台网站建设公司/营销推广案例
  • 从线性回归到神经网络到自注意力机制 —— 激活函数与参数的演进
  • 如何使用DeepSeek解析长pdf的文本
  • 实践笔记-小端模式下的寄存器数据输入技巧;图形化界面配置注意事项。
  • Vue 3中watch的返回值:解锁监听的隐藏技巧
  • JAVA经典面试题:数据库调优
  • 数据结构:查找表