aop原理

news2024/11/26 13:42:21

1. 使用

1.1 依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

1.2 定义切面类

定义一个切面类,指定增强的方法,方法前两个注解必须有
execution( * com.lzp..controller..(…)) 代表 com.lzp包下所有包下controller包下所有类的所有方法都会被代理,就代表所有,第一个是所有方法的返回值,第一个前面还有方法修饰符,public之类的,缺省就表示所有修饰符,最后一个代表所有方法名,(…)代表方法参数,…是指所有参数,倒数第二个代表类,第二个*代表包。这样调用对应包下的方法时就会被增强。
所以顺序就是 修饰符 返回值 包名 类名 方法名 方法参数

@Aspect
@Component
@Slf4j
public class TestAspect {

    @Around("execution( * com.lzp.*.controller.*.*(..))")
    public void arround(ProceedingJoinPoint pjp) {
        try {
            log.info("1、Around:方法环绕开始.....");
            Object o =  pjp.proceed();
            log.info("3、Around:方法环绕结束,结果是 :" + o);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}
  • 表达式多种多样,根据需求配置即可
  • 表达式还可以针对注解使用 自定义和非自定义注解都可以
  • 表达式参考

1.3 定义被增强的方法

在规则配置的包下的类中定义方法即可,这样在调用test01方法时,就会进行增强了。

@RestController
public class TestController {
    protected final  Log logger = LogFactory.getLog(getClass());
    @GetMapping("/")
    public String test01(){
        if(logger.isDebugEnabled()){
            logger.fatal(123);
        }
        return "hello11122222";
    }
}

注意:切面类和被增强方法所在的类,都要注册到sping中。

2. 自动配置

2.1 AopAutoConfiguration

引入依赖后会自动配置aop
AopAutoConfiguration

@Configuration(proxyBeanMethods = false)
//引入依赖后这里就会通过
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(Advice.class)
	static class AspectJAutoProxyingConfiguration {

		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = false)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
		static class JdkDynamicAutoProxyConfiguration {

		}
		//默认使用这个cglib创建代理 @EnableAspectJAutoProxy是开启aop功能
		@Configuration(proxyBeanMethods = false)
		@EnableAspectJAutoProxy(proxyTargetClass = true)
		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
				matchIfMissing = true)
		static class CglibAutoProxyConfiguration {

		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
	@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
			matchIfMissing = true)
	static class ClassProxyingConfiguration {

		@Bean
		static BeanFactoryPostProcessor forceAutoProxyCreatorToUseClassProxying() {
			return (beanFactory) -> {
				if (beanFactory instanceof BeanDefinitionRegistry) {
					BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
					AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
					AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
				}
			};
		}
	}
}

2.2 @EnableAspectJAutoProxy

@EnableAspectJAutoProxy会引入AspectJAutoProxyRegistrar,这个Registrar会引入AnnotationAwareAspectJAutoProxyCreator的bean定义信息。关键类,aop的功能就是由它和它的父类们实现的。

AnnotationAwareAspectJAutoProxyCreator继承了AbstractAutoProxyCreator实现了InstantiationAwareBeanPostProcessor接口

AbstractAutowireCapableBeanFactory#createBean方法在执行doCreateBean之前会执行本类的resolveBeforeInstantiation方法。

	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					//关键方法
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}

resolveBeforeInstantiation方法会调用本类的applyBeanPostProcessorsBeforeInstantiation方法
遍历processors 调用对应postProcessBeforeInstantiation方法,这里的关键是AnnotationAwareAspectJAutoProxyCreator这个processor,上面自动配置引入的就是这个类,会执行他的父类AbstractAutoProxyCreator#postProcessBeforeInstantiation方法
在这里插入图片描述
aop的功能由此开始实现

3. 原理

3.1 解析切面类

解析切面类由
AbstractAutoProxyCreator#postProcessBeforeInstantiation完成
重写InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法
这里的逻辑是普通类进入判断,advisedBeans的value设置为false,需要增强的类不会进入判断,通过shouldSkip方法获取到切面中配置的增强方法(也就是加了@around注解的方法)
这里普通的类(包括切面类)会进入判断,但是切面类中配置的增强类不会进入判断,
在这里插入图片描述

3.1.1 第一个判断

加了@aspect的类会通过
AnnotationAwareAspectJAutoProxyCreator重写了isInfrastructureClass方法,所以会执行AnnotationAwareAspectJAutoProxyCreator类的isInfrastructureClass方法
在这里插入图片描述

3.1.2 第二个判断

需要被增强的类 普通类会进入,步骤1的TestController不应该跳过
会调用子类的子类AspectJAwareAdvisorAutoProxyCreator#shouldSkip方法
在这里插入图片描述
AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
在这里插入图片描述
BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
也就是找到切面类。步骤1的TestAspect类

	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;
		//缓存中没有的话去获取,这里在第一个bean执行createBean方法时就会为空,然后创建缓存,后面的bean实例化时就可以直接获取了。
		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					//获取到所有的beanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					//遍历所有的beanName
					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.
						Class<?> beanType = this.beanFactory.getType(beanName, false);
						if (beanType == null) {
							continue;
						}
						//只有是加了@Aspect注解的类才会进入判断
						if (this.advisorFactory.isAspect(beanType)) {
							//先把名字加到缓存中,方法开始就是从这里拿到切面类的名字
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								//构建工厂
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								//关键方法 解析切面类中的增强方法		
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								if (this.beanFactory.isSingleton(beanName)) {
									//加到缓存中 classAdvisors也就是增强方法 可能有多个
									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;
	}

有的话直接从缓存中拿
在这里插入图片描述
没有的话需要获取到切面类,然后解析。

3.2 解析切面类流程

在实例化第一个单例bean时,会对我们定义的切面类进行解析 然后缓存到advisorsCache中,key是beanName,value是advisor数组。每个切面类可能有多个增强方法
过程就是获取到切面类,然后获取到所有切面类的方法(除了pointcut注解的方法),然后遍历,封装成Advisor类型。
ReflectiveAspectJAdvisorFactory#getAdvisors

	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		//获取到切面类
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		//切面类的name
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
		//我们需要用装饰器包装 MetadataAwareAspectInstanceFactory,以便它只实例化一次。
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
		//获取遍历切面类所有的增强方法 @before @around @after 
		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).
			//遍历每个方法 一个一个解析
			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;
	}

ReflectiveAspectJAdvisorFactory#getAdvisor

	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
		//找到注解及注解配置的表达式 @around @after @before
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
		//针对每个增强方法 构建一个对象
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}
	@Nullable
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
		//找到注解及注解配置的表达式 @around @after @before
		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;
	}

InstantiationModelAwarePointcutAdvisorImpl#InstantiationModelAwarePointcutAdvisorImpl

	public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

        //当前的切点表达式
        this.declaredPointcut = declaredPointcut;
        //切面的class对象
        this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
        //切面方法的名称
        this.methodName = aspectJAdviceMethod.getName();
        //切面方法的参数类型
        this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
        //切面方法对象
        this.aspectJAdviceMethod = aspectJAdviceMethod;
        //aspectj的通知工厂
        this.aspectJAdvisorFactory = aspectJAdvisorFactory;
        //aspect的实例工厂
        this.aspectInstanceFactory = aspectInstanceFactory;
        //切面的顺序
        this.declarationOrder = declarationOrder;
        //切面的名称
        this.aspectName = aspectName;
		//是否需要延时加载
		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			// Static part of the pointcut is a lazy type.
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

			// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
			// If it's not a dynamic pointcut, it may be optimized out
			// by the Spring AOP infrastructure after the first evaluation.
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			//将切面中的通知构造为advice通知对象
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}

在这里插入图片描述
ReflectiveAspectJAdvisorFactory#getAdvice
getAdvisors方法中的getAdvisor方法需要的对象了。每个增强方法都会是一个Advice类型

	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
		//切面类的class
		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);
		//获取切面方法上的注解
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
		if (!isAspect(candidateAspectClass)) {
			throw new AopConfigException("Advice must be declared inside an aspect type: " +
					"Offending method '" + candidateAdviceMethod + "' in class [" +
					candidateAspectClass.getName() + "]");
		}

		if (logger.isDebugEnabled()) {
			logger.debug("Found AspectJ method: " + candidateAdviceMethod);
		}
		//最终返回的类型
		AbstractAspectJAdvice springAdvice;
		//根据注解类型构建
		switch (aspectJAnnotation.getAnnotationType()) {
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			// 参数是 当前方法 切点表达式 工厂
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			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);
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

这样就把切面类的增强方法都解析完了。除了@pointcut的方法。

3.3 注意

父类AbstractAutoProxyCreator 实现了两个接口InstantiationAwareBeanPostProcessorBeanPostProcessor

  • InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation方法在createBean方法doCreateBean之前会调用。作用就是解析切面类
  • BeanPostProcessor接口的postProcessAfterInitialization方法在创建完bean,初始化(initializeBean)时调用。作用是为需要增强的类创建代理

AbstractAutoProxyCreator#postProcessAfterInitialization
重写接口BeanPostProcessor接口的postProcessAfterInitialization方法
在这里插入图片描述

3.4 创建代理

在createBean方法的doCreateBean方法中执行实例化bean,填充bean,和初始化bean,在初始化bean方法initializeBean中,会执行postProcessBeforeInitialization、postProcessAfterInitialization方法,关于aop创建代理是在AbstractAutoProxyCreator类的postProcessAfterInitialization方法中。
在这里插入图片描述
AbstractAutoProxyCreator#wrapIfNecessary

	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		//普通类会把advisedBeans中对应的bean的value设置为false,而切面类中指定的增强类则不会
		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.
		//如果有匹配的通知,就创建代理对象 关键方法
		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;
	}

AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean方法会调用AbstractAdvisorAutoProxyCreator#findEligibleAdvisors方法

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		 //找到Spring IoC容器中所有的候选通知 也就是切面类中加了@around @beafore @after注解的方法
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//判断找到的通知能不能作用到当前的类上 关键
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		//对我们的advisor进行排序
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
在这里插入图片描述
AopUtils#findAdvisorsThatCanApply

	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		//为空直接返回
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		//遍历
		for (Advisor candidate : candidateAdvisors) {
			//这里不会进入 因为没有实现IntroductionAdvisor 
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		//遍历 
		for (Advisor candidate : candidateAdvisors) {
			//这里不会进入 因为没有实现IntroductionAdvisor 
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			//会进这个判断
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		return eligibleAdvisors;
	}

AopUtils#canApply

	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
		//这里不会进入 因为没有实现IntroductionAdvisor 
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			//继续重载的canApply
			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
		}
		else {
			// It doesn't have a pointcut so we assume it applies.
			return true;
		}
	}

AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>, boolean)
如果该方法返回true就表示匹配,就添加到合适的集合eligibleAdvisors中,然后为当前类创建代理

	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<>();
		//断当前class是不是代理的class对象 不是的话加到classes 
		if (!Proxy.isProxyClass(targetClass)) {
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		//把当前类实现的接口的class都加进来
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
		//遍历当前类和当前类实现的接口
		for (Class<?> clazz : classes) {
			//获取到当前类的所有方法
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			//遍历看当前方法是否满足增强条件 也就是能否满足表达式的配置 能满足就返回true
			//@Around("execution( * com.lzp.*.controller.*.*(..))")
			for (Method method : methods) {
				if (introductionAwareMethodMatcher != null ?
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

3.4.1 构建切点表达式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

回到AbstractAutoProxyCreator#wrapIfNecessary方法,获取到specificInterceptors了,然后会创建当前类的代理对象,然后返回
在这里插入图片描述
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);
		//cglib
		if (proxyFactory.isProxyTargetClass()) {
			// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
			if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
				// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
				for (Class<?> ifc : beanClass.getInterfaces()) {
					proxyFactory.addInterface(ifc);
				}
			}
		}
		//jdk
		else {
			// No proxyTargetClass flag enforced, let's apply our default checks...
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
		
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		//添加增强方法 也就是@around @after @before
		proxyFactory.addAdvisors(advisors);
		//目标类
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// Use original ClassLoader if bean class not locally loaded in overriding class loader
		ClassLoader classLoader = getProxyClassLoader();
		if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
			classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
		}
		//执行代理工厂的创建代理方法
		return proxyFactory.getProxy(classLoader);
	}

ProxyFactory#getProxy(java.lang.ClassLoader)
在这里插入图片描述
创建方法肯定是创建了cglib代理工厂
注:springboot aop默认使用cglib动态代理,切换为jdk动态代理的方法是
spring.aop.proxy-target-class=false
jdk动态代理时:如果代理类没有实现接口也创建cglib代理,否则创建jdk代理

CglibAopProxy#getProxy(java.lang.ClassLoader)

	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating CGLIB proxy: " + 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 (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
				proxySuperClass = rootClass.getSuperclass();
				Class<?>[] additionalInterfaces = rootClass.getInterfaces();
				for (Class<?> additionalInterface : additionalInterfaces) {
					this.advised.addInterface(additionalInterface);
				}
			}

			// Validate the class, writing log messages as necessary.
			validateClassIfNecessary(proxySuperClass, classLoader);

			// 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 ClassLoaderAwareGeneratorStrategy(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 | IllegalArgumentException ex) {
			throw new AopConfigException("Could not generate CGLIB subclass of " + 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);
		}
	}

	protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
		enhancer.setInterceptDuringConstruction(false);
		enhancer.setCallbacks(callbacks);
		return (this.constructorArgs != null && this.constructorArgTypes != null ?
				enhancer.create(this.constructorArgTypes, this.constructorArgs) :
				enhancer.create());
	}

最终创建的代理
在这里插入图片描述

4.总结

aop的功能就是不改变原方法内容,对原方法进行增强,想要实现这个功能一定就是动态代理了。
实现原理:
1.关键类:AnnotationAwareAspectJAutoProxyCreator,自动配置中的@EnableAspectJAutoProxy注解会引入这个类,aop的功能就是通过这个类以及它的父类们共同完成的。
2.关键方法:
AnnotationAwareAspectJAutoProxyCreator的父类(不是直接父类)AbstractAutoProxyCreator 实现了两个接口InstantiationAwareBeanPostProcessorBeanPostProcessor
1.1.AbstractAutoProxyCreator类实现接口InstantiationAwareBeanPostProcessor重写的postProcessBeforeInstantiation方法。
这个方法在bean实例化时的createBean方法中执行,在doCreateBean方法之前,在实例化第一个单例bean时,对所有我们自定义的切面类进行解析。然后放到缓存中,key是切面类name,value是advisor类型的数组,因为一个切面类可以有多个增强方法。
1.2.AbstractAutoProxyCreator类实现接口BeanPostProcessor重写了postProcessAfterInitialization方法。
这个方法在bean实例化时的initializeBean方法完成,在doCreateBean方法中,populateBean方法之后。对所有正在实例化的bean进行判断,看能否和1.1中生成的增强方法进行匹配,能匹配的话就对当前类创建代理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/616032.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Axure教程—滚动加载(中继器 )

本文将教大家如何用AXURE中的中继器制作滚动加载效果 一、效果介绍 如图&#xff1a; 预览地址&#xff1a;https://awjggr.axshare.com 下载地址&#xff1a;https://download.csdn.net/download/weixin_43516258/87867798?spm1001.2014.3001.5503 二、功能介绍 向下滚动鼠…

联想YOGA Pro14s电脑运行时总是蓝屏怎么办?

联想YOGA Pro14s电脑运行时总是蓝屏怎么办&#xff1f;最近有用户在使用电脑的时候&#xff0c;电脑总是会自动变成蓝屏&#xff0c;导致自己的操作中断。那么遇到这个情况要怎么去进行问题的解决呢&#xff1f;接下来我们来看看以下的详细解决方法分享吧。 准备工作&#xff1…

通过python封装关键词搜索1688商品列表数据API、1688商品列表API接口、1688API接口

1688商品详情接口是一种用于访问阿里巴巴旗下的批发市场平台上的商品列表信息的API接口。通过该接口&#xff0c;可以获取商品的详细信息&#xff0c;包括商品名称、规格、价格、描述、图片等。这些信息对于买家和卖家来说都非常重要&#xff0c;可以帮助他们更好地了解商品&am…

MyBatisPlus3-条件查询和映射问题(字段、表名)

1. 条件查询三种方式 条件查询多用第三种&#xff1b; 链式写表示且的关系&#xff0c;中间加上or()表示或的关系&#xff1b; 给出相应示例代码&#xff1a; Test public void testGetList(){//方式一&#xff1a;按条件查询/*QueryWrapper<User> userQueryWrapper new…

基于WebGL的智慧化工三维可视化管理系统

前言 作为全球化学品第一生产大国&#xff0c;我国危险化学品规模总量大、涉及品种多、应用范围广、管理链条长、安全风险高&#xff0c;历来是防范化解重大安全风险的重点领域。 危险化学品领域频繁发生的典型事故&#xff0c;暴露出传统安全风险管控手段问题突出。 建设背景…

【裸机驱动LED】使用汇编代码驱动LED(一)—— 寄存器解析篇

为了后续使用C语言驱动LED&#xff0c;事先学习汇编代码驱动LED&#xff0c;有如下好处&#xff1a; 熟悉一些基本的汇编语法了解驱动LED的基本流程了解驱动LED需要用到哪些寄存器作为一个初学者&#xff0c;可以锻炼自己阅读开发文档的能力 本文的主要目的是了解驱动LED的基…

【手撕Spring源码】SpringBoot启动过程中发生了什么?

文章目录 SpringBoot启动过程启动详解启动演示启动过程总结 SpringBoot启动过程 启动详解 SpringBoot的启动分为两个部分&#xff1a; 构造SpringApplication执行run方法 接下来我们先来看看构造方法里面都做了什么事情。 第一步&#xff1a;记录 BeanDefinition 源 大家知…

Jenkins配置邮件通知+钉钉通知,任务构建状态随时掌握

1.前言 Hello&#xff0c;各位小伙伴&#xff0c;大家好&#xff01;&#xff01;&#xff01; 在前面的文章中&#xff0c;我们实现了用Maven项目任务和Pipeline流水线任务来完成对项目的自动化部署。 DockerJenkinsGitee自动化部署maven项目 DockerJenkinsGiteePipeline部…

0001欧几里得算法

首先我们先了解欧几里得这个人。俗话说&#xff1a;不了解一个人&#xff0c;很难走进他的思想。欧几里得是约公元前330年~公元前275年的古希腊数学家&#xff0c;被称为“几何之父”。《几何原本》就是他的著作。而欧几里得算法是《几何原本》中的一个用于求两个数的最大公约数…

以AI为灯,照亮医疗放射防护监管盲区

相信绝大部分人都有在医院拍X光片的经历&#xff0c;它能够让医生更方便快速地找出潜在问题&#xff0c;判断病人健康状况&#xff0c;是医疗诊断过程中的常见检查方式。但同时X射线也是一把双刃剑&#xff0c;它的照射量可在体内累积&#xff0c;对人体血液白细胞有杀伤力&…

mysql加索引,数据库卡死

公司的一个内部项目&#xff0c;由于突然导入了几十万的数据&#xff0c;数据量翻了一倍&#xff0c;导致了某个页面打开很慢。通过sql日志看到主要是由于慢查询引起的&#xff0c;通过explain这个sql&#xff0c;发现主要是由于这个SQL没有命中索引&#xff0c;进行了全表扫描…

原型模式的用法

文章目录 一、原型模式的用法1.1 介绍1.2 结构1.3 原型模式类图1.4 实现1.4.1 克隆的分类1.4.2 代码 1.5 "三好学生"奖状案例1.5.1 "三好学生"奖状类图1.5.2 代码 1.6 深、浅克隆的区分1.6.1 浅克隆1.6.2 深克隆 一、原型模式的用法 1.1 介绍 用一个已经…

STL(结)

STL&#xff08;结&#xff09; map存储结构基本操作equal_range遍历方式 插入 multimapsetunordered_mapmap和无序map的异同mapunordered_map map 存储结构 map容器的底层存储是一个红黑树&#xff0c;遍历方式都是按照中序遍历的方式进行的。 int main() {std::map<int…

数组降维

写一个函数&#xff0c;打印数组内的内容&#xff0c;代码为&#xff1a; #include<stdio.h>void show_arr(int arr[], int num) {int i 0;for (i 0; i < num; i){printf("%d ", arr[i]);}printf("\n"); } int main() {int arr[] { 1,2,3,4,5…

Servlet Cookie基本概念和使用方法

目录 Cookie 介绍 Cookie 主要有两种类型&#xff1a;会话 Cookie 和持久 Cookie。 Cookie使用步骤 使用Servlet和Cookie实现客户端存储的登录功能示例&#xff1a; LoginServlet类 index.jsp 删除Cookie 浏览器中查看Cookie的方法 Cookie 介绍 Cookie 是一种在网站和…

win10下载安装mysql8.0版本

打开官网下载&#xff1a;https://dev.mysql.com/downloads/mysql/ 下载完成后解压&#xff0c;这里我是直接放在C盘 然后打开mysql目录文件夹新建my.ini文件,my.ini文件内容如下&#xff0c;需要修改两个地方&#xff0c;其中datadir你自己的mysql的安装目录&#xff0c;data…

如何在线压缩png图片?png压缩图片大小的方法介绍

压缩PNG图片大小的优点 随着数字化时代的发展&#xff0c;PNG格式已成为一种常见的图片格式。然而&#xff0c;由于高分辨率、高色深等原因&#xff0c;PNG图片通常具有较大的文件体积&#xff0c;导致在传输、存储和网页加载等方面会产生不必要的负担。因此&#xff0c;对于需…

ai绘画生成古风场景怎么弄?告诉你怎么ai绘画

随着人工智能技术的不断发展&#xff0c;ai绘画已经成为一个令人着迷的领域。一些软件利用深度学习算法和生成对抗网络等技术&#xff0c;能够帮助艺术家和爱好者创造出令人惊叹的艺术作品。今天我就来跟大家分享一下如何一键ai绘画&#xff0c;感兴趣的朋友就跟我一起看下去吧…

《文体用品与科技》期刊简介及投稿要求

《文体用品与科技》期刊简介&#xff1a; 主管单位&#xff1a;中国轻工业联合会 主办单位&#xff1a;中国文教体育用品协会、全国文教体育用品信息中心、北京市文教体育用品研究所 国际刊号&#xff1a; ISSN1006-8902 国内刊号;CN:11-3762/TS 邮发代号;82-21932 发表周…

DDR跑不到速率后续来了,相邻层串扰深度分析!

高速先生成员&#xff1a;黄刚 就在刚刚&#xff0c;雷豹把他对叠层的调整方式和改善后的仿真结果给师傅Chris看完后&#xff0c;Chris给雷豹点了个大大的赞&#xff0c;因为优化的方式其实不需要大改DDR的走线&#xff0c;只需要把相邻层的信号最大限度的拉开&#xff0c;同时…