Spring之AOP解析


一、AOP的关键概念

AOP:Aspect Oriented Programming的缩写,意为:面向切面编程。

  1. Joinpoint(连接点):程序执行中的候选者点, 例如一个被调用的方法, 或者是一个异常的处理; 简单来讲和方法有关的前前后后都是连接点。
  2. Pointcut(切点):如果连接点相当于数据中的记录,那么切点相当于查询条件,一个切点可以匹配多个连接点。所以切点表示一组Joinpoint,这些Jointpoint或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。
  3. Advice(通知/增强):通知是织入到目标类连接点上的一段程序代码,包含增强的横切代码。
  4. Advisor(顾问/增强器):Advisor是切面的另一种实现,绑定通知跟切点,增强器中包含通知和切点属性。
  5. Introduction(引介):引介是一种特殊的通知,它为类添加一些属性和方法。这样,即使一个业务类原本没有实现某个接口,通过引介功能,可以动态的为该业务类添加接口的实现逻辑,让业务类成为这个接口的实现类。
  6. Interceptor(拦截器):在Advice的基础上扩展定义,定义了通知的增强方式,也就是通过对Joinpoint(连接点)的拦截。一个通用的拦截器可以拦截发生在基础程序中的运行时事件。
  7. Aspect(切面): 切面是由Pointcut(切点)和Advice(通知)组成的,它包括了对横切关注功能的定义,也包括了对连接点的定义。
  8. TargetSource(目标对象):包含连接点的对象。也被称作被通知或被代理对象。
  9. Proxy(代理对象):包含了原始对象的代码(是在合适的位置调用目标对象的方法)和增加后的代码(Advice通知的内容)的那个对象。
  10. Weaving(织入):织入是将Advice通知添加到目标类具体连接点上的过程,AOP有三种织入方式:①编译期织入:需要特殊的Java编译期(例如AspectJ的ajc);②装载期织入:要求使用特殊的类加载器,在装载类的时候对类进行增强;③运行时织入:在运行时为目标类生成代理实现增强。AspectJ采用了编译期织入和装载期织入的方式,Spring采用了动态代理的方式实现了运行时织入。

二、Advice(通知、增强)

// Advice是一个标记接口
public interface Advice {

}

// 拦截器也是一个Advice接口,是一个标记接口
public interface Interceptor extends Advice {

}

// BeforeAdvice 也是一个标记接口
public interface BeforeAdvice extends Advice {

}

public interface MethodBeforeAdvice extends BeforeAdvice {

	/**
	 * Callback before a given method is invoked.
	 * @param method method being invoked
	 * @param args arguments to the method
	 * @param target target of the method invocation. May be {@code null}.
	 * @throws Throwable if this object wishes to abort the call.
	 * Any exception thrown will be returned to the caller if it's
	 * allowed by the method signature. Otherwise the exception
	 * will be wrapped as a runtime exception.
	 */
	void before(Method method, Object[] args, @Nullable Object target) throws Throwable;

}

// AfterAdvice 也是一个标记接口
public interface AfterAdvice extends Advice {

}

// ThrowsAdvice 也是一个标记接口
public interface ThrowsAdvice extends AfterAdvice {

}

public interface AfterReturningAdvice extends AfterAdvice {

	/**
	 * Callback after a given method successfully returned.
	 * @param returnValue the value returned by the method, if any
	 * @param method method being invoked
	 * @param args arguments to the method
	 * @param target target of the method invocation. May be {@code null}.
	 * @throws Throwable if this object wishes to abort the call.
	 * Any exception thrown will be returned to the caller if it's
	 * allowed by the method signature. Otherwise the exception
	 * will be wrapped as a runtime exception.
	 */
	void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable;

}

Advice有以下几种常见的类型:

  1. AspectJMethodBeforeAdvice:前置通知。AspectJ中 before 属性对应的通知(@Before标注的方法会被解析成该通知),在切面方法执行之前执行。
  2. AspectJAfterReturningAdvice:后置通知。AspectJ中 afterReturning 属性对应的通知(@AfterReturning 标注的方法会被解析成该通知),在切面方法执行之后执行,如果有异常,则不执行。注意:该通知与AspectJMethodBeforeAdvice对应。
  3. AspectJAroundAdvice:环绕通知。AspectJ中 around 属性对应的通知(@Around标注的方法会被解析成该通知),在切面方法执行前后执行。
  4. AspectJAfterAdvice:返回通知。AspectJ中 after 属性对应的通知(@After 标注的方法会被解析成该通知),不论是否异常都会执行。
  5. AspectJAfterThrowingAdvice:异常通知,AspectJ中 after 属性对应的通知(@AfterThrowing标注的方法会被解析成该通知),在连接点抛出异常后执行。

Advice是一个标记接口,所有的advice都直接或者间接继承了interceptor(拦截器)接口,也就是说,所有的通知实际上就是拦截器。

通知的执行顺序为: around->before->方法本身->around->after->afterReturning

三、 Advisor(顾问/增强器)

Advisor是切面的另一种实现,绑定通知跟切点,包含advice和pointcut属性。

public interface Advisor {

	Advice EMPTY_ADVICE = new Advice() {};

	Advice getAdvice();

	boolean isPerInstance();
}

public interface PointcutAdvisor extends Advisor {
	Pointcut getPointcut();
}

 InstantiationModelAwarePointcutAdvisorImpl:springboot自动装配的顾问类型。是最常用的一种顾问实现。在注解实现的切面中,所有@Aspect类,都会被解析成该对象。

四、 Pointcut(切点)

public interface Pointcut {

	ClassFilter getClassFilter(); //获取类过滤器
    
	MethodMatcher getMethodMatcher(); // 获取方法匹配器
    
	Pointcut TRUE = TruePointcut.INSTANCE;
}

public interface ClassFilter {
    // 指定的类是否匹配
	boolean matches(Class<?> clazz);
    
	ClassFilter TRUE = TrueClassFilter.INSTANCE;
}

public interface MethodMatcher {

	boolean matches(Method method, Class<?> targetClass); // 测试此切入点是否与目标类上的给定方法匹配,当创建AOP代理时可以执行此评估,以避免对每个方法调用进行测试

	boolean isRuntime(); //如果返回true,则在每次方法调用时都会调下面的用三个参数匹配的方法,这允许切入点在执行目标通知之前查看传递给方法调用的参数

	boolean matches(Method method, Class<?> targetClass, Object... args);

	MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
}

  1.  AnnotationMatchingPointcut:注解匹配切点。根据类上或方法上是否存在指定的注解判断切点的匹配性,如果没有显示指定注解,则匹配所有。
  2. DynamicMethodMatcherPointcut:动态方法匹配器切点。它本质上是一个方法匹配器,但同时具有了切点的功能。
  3. ComposablePointcut:可组合的切点。这种切点可以与或逻辑,任意组合其他的Pointcut、ClassFilter和MethodMatcher。其本质是通过ClassFilters和MethodMatchers两个工具类进行Pointcut内部组件的组合。
  4. JdkRegexpMethodPointcut: JDK正则表达式切点,即使用正则表达式描述方法的拦截规则和排除规则。
  5. AspectJExpressionPointcut:AspectJ切点表达式切点。顾名思义,使用AspectJ的切点表达式描述筛选规则。表达式基本语法如下(非完整语法):execution(<方法修饰符>? <方法返回值类型> <包名>.<类名>.<方法名>(<参数类型>) [throws <异常类型>]?); 其中,‘*’代表0个或多个任意字符,包名中的..(两个点)代表当前包及其子包,参数列表中的..代表任意个参数。如:execution(public static * *..*.*(..) throws *),此表达式匹配所有方法。

五、TargetSource(目标对象)

public interface TargetSource extends TargetClassAware {

	/**
	 * Return the type of targets returned by this {@link TargetSource}.
	 * <p>Can return {@code null}, although certain usages of a {@code TargetSource}
	 * might just work with a predetermined target class.
	 * @return the type of targets returned by this {@link TargetSource}
	 */
	@Override
	@Nullable
	Class<?> getTargetClass();

	/**
	 * Will all calls to {@link #getTarget()} return the same object?
	 * <p>In that case, there will be no need to invoke {@link #releaseTarget(Object)},
	 * and the AOP framework can cache the return value of {@link #getTarget()}.
	 * @return {@code true} if the target is immutable
	 * @see #getTarget
	 */
	boolean isStatic();

	/**
	 * Return a target instance. Invoked immediately before the
	 * AOP framework calls the "target" of an AOP method invocation.
	 * @return the target object which contains the joinpoint,
	 * or {@code null} if there is no actual target instance
	 * @throws Exception if the target object can't be resolved
	 */
	@Nullable
	Object getTarget() throws Exception;

	/**
	 * Release the given target object obtained from the
	 * {@link #getTarget()} method, if any.
	 * @param target object obtained from a call to {@link #getTarget()}
	 * @throws Exception if the object can't be released
	 */
	void releaseTarget(Object target) throws Exception;

}

 TargetSource被用于获取当前MethodInvocation(方法调用)所需要的target(目标对象),这个target通过反射的方式被调用(如:method.invode(target,args))。换句话说,proxy(代理对象)代理的不是target,而是TargetSource。

4个简单实现包括:

(1)EmptyTargetSource:静态目标源,当不存在target目标对象,或者甚至连targetClass目标类都不存在(或未知)时,使用此类实例。

(2)HotSwappableTargetSource:动态目标源,支持热替换的目标源,支持spring应用运行时替换目标对象。

(3)JndiObjectTargetSource:spring对JNDI管理bean的支持,static属性可配置。

(4)SingletonTargetSource:静态目标源,单例目标源。Spring的AOP框架默认为受IoC容器管理的bean创建此目标源。换句话说,SingletonTargetSource、proxy与目标bean三者的声明周期均相同。如果bean被配置为prototype,则spring会在每次getBean时创建新的SingletonTargetSource实例。

3大类实现包括:

(1)AbstractBeanFactoryBasedTargetSource:此类目标源基于IoC容器实现,也就是说target目标对象可以通过beanName从容器中获取。此类又扩展出:① SimpleBeanTargetSource:简单实现,直接调用getBean从容器获取目标对象;② LazyInitTargetSource:延迟初始化目标源,子类可重写postProcessTargetObject方法后置处理目标对象;③AbstractPrototypeBasedTargetSource:原型bean目标源,此抽象类可确保beanName对应的bean的scope属性为prototype。其子类做了简单原型、池化原型、线程隔离原型这3种实现。

(2)AbstractRefreshableTargetSource:可刷新的目标源。此类实现可根据配置的刷新延迟时间,在每次获取目标对象时自动刷新目标对象。

(3)AbstractLazyCreationTargetSource:此类实现在调用getTarget()获取时才创建目标对象

六 、示例

前置准备代码:

@Data
@AllArgsConstructor
public class Book {
    private String name;
}

// 接口定义
public interface BookService {
    Book create(String name);
    Book query(String name);
}

@Component
public class BookServiceImp implements BookService{
    @Override
    public Book create(String name) {
        System.out.println("BookServiceImp.create called");
        return new Book(name);
    }

    @Override
    public Book query(String name) {
        System.out.println("BookServiceImp.query called");
        return new Book(name);
    }
}

@Component
public class LogBeforeAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("准备执行方法:" + method.getName() + ", 参数列表:" + Arrays.toString(args));
    }
}

@Component
public class LogAfterReturningAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("方法返回:" + returnValue);
    }
}

3.1 ProxyFactoryBean 注入bean工厂

ProxyFactoryBean是一个代理工厂,指定目标对象,代理接口和拦截器/增强器后,可以生产指定代理对象的代理工厂的bean(不修改原有的bean)。ProxyConfig中主要封装了代理的通用处理逻辑,比如设置目标类,设置使用cglib还是java proxy等一些基础配置

3.1.1 直接设置拦截器实现类级别的拦截

ProxyFactoryBean设置拦截器,实现类级别的拦截:

@SpringBootApplication
public class Springboot001Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Springboot001Application.class, args);

        //未代理对象
        BookService bookService = (BookService)run.getBean("bookServiceImp");
        bookService.create("小白学习aop:原始bean");

        // 代理对象
        bookService = (BookService)run.getBean("bookServiceProxy");
        bookService.create("小白学习aop:代理bean");

    }

    @Bean
    public ProxyFactoryBean bookServiceProxy() throws ClassNotFoundException {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();

        // 设置拦截器的bean名称(advice通知)
        proxyFactoryBean.setInterceptorNames("logBeforeAdvice", "logAfterReturningAdvice");

        // 设置代理的接口
        proxyFactoryBean.setProxyInterfaces(new Class[]{BookService.class});

        // 设置目标对象
        proxyFactoryBean.setTargetName("bookServiceImp");

        return proxyFactoryBean;
    }

}

执行结果:

3.1.2 设置增强器实现方法级别的拦截

ProxyFactoryBean设置增强器,实现类方法级别的拦截(以NameMatchMethodPointcutAdvisor 为例,匹配方法名称):

@SpringBootApplication
public class Springboot001Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Springboot001Application.class, args);

        //未代理对象
        BookService bookService = (BookService)run.getBean("bookServiceImp");
        bookService.create("小白学习aop:原始bean");

        // 代理对象
        bookService = (BookService)run.getBean("bookServiceProxy");
        bookService.create("小白学习aop:代理bean");

    }

    @Bean
    public NameMatchMethodPointcutAdvisor bookServiceBeforeAdvisor(Advice logBeforeAdvice) {
        NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(logBeforeAdvice);
        advisor.setMappedName("create"); // 匹配create方法
        return advisor;
    }

    @Bean
    public NameMatchMethodPointcutAdvisor bookServiceAfterReturnAdvisor(Advice logAfterReturningAdvice) {
        NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(logAfterReturningAdvice);
        advisor.setMappedName("create"); // 匹配create方法
        return advisor;
    }

    @Bean
    public ProxyFactoryBean bookServiceProxy() throws ClassNotFoundException {
        ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();

        // 使用增强器设置拦截器
        proxyFactoryBean.setInterceptorNames("bookServiceBeforeAdvisor", "bookServiceAfterReturnAdvisor");

        // 设置代理的接口
        proxyFactoryBean.setProxyInterfaces(new Class[]{BookService.class});

        // 设置目标对象
        proxyFactoryBean.setTargetName("bookServiceImp");

        return proxyFactoryBean;
    }

执行结果:

3.1.3 ProxyFactoryBean源码分析

     ProxyFactoryBean实现了FactoryBean接口,是一个工厂bean,实现了getObject方法:

	public Object getObject() throws BeansException {
		initializeAdvisorChain(); //初始化增强器链
		if (isSingleton()) {
			return getSingletonInstance(); // 获取单例对象
		}
		else {
			if (this.targetName == null) {
				logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
						"Enable prototype proxies by setting the 'targetName' property.");
			}
			return newPrototypeInstance();
		}
	}

	private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
		// 判断是否已经初始化过
        if (this.advisorChainInitialized) {
			return;
		}

		if (!ObjectUtils.isEmpty(this.interceptorNames)) {
		    // ... 省略部分代码

			// 获取所有的拦截器bean名称,并从bean工厂中获取拦截器实例,加入增强器链
			for (String name : this.interceptorNames) {
			    // ... 省略部分代码
					Object advice;
					if (this.singleton || this.beanFactory.isSingleton(name)) {
						advice = this.beanFactory.getBean(name);
					}
					else {
						advice = new PrototypePlaceholderAdvisor(name);
					}
                
                    // 将通知加入增强器链
					addAdvisorOnChainCreation(advice);
			}
		}

		this.advisorChainInitialized = true; // 设置已经初始化
	}

	private void addAdvisorOnChainCreation(Object next) {
        // namedBeanToAdvisor将bean对象转换为增强器对象
		addAdvisor(namedBeanToAdvisor(next));
	}

	private Advisor namedBeanToAdvisor(Object next) {
        // ... 省略部分代码,advisorAdapterRegistry未设置时默认为DefaultAdvisorAdapterRegistry
		return this.advisorAdapterRegistry.wrap(next);
	}

    // 获取单例对象
	private synchronized Object getSingletonInstance() {
        // singletonInstance为代理对象,如果为空,则创建代理对象
		if (this.singletonInstance == null) {
			// ... 省略部分代码
			super.setFrozen(this.freezeProxy);
            // createAopProxy 创建AOP代理,getProxy通过代理获取代理对象
			this.singletonInstance = getProxy(createAopProxy());
		}
		return this.singletonInstance;
	}

    // 创建AOP代理
	protected final synchronized AopProxy createAopProxy() {
		// ... 省略部分代码,aop代理工厂默认为DefaultAopProxyFactory
        // 创建代理对象时,入参为this,也就是创建ProxyFactoryBean对象的代理对象
		return getAopProxyFactory().createAopProxy(this);
	}

    // 获取代理对象,如果aopProxy代理是JdkDynamicAopProxy类型,使用JDK动态代理创建代理对象
	protected Object getProxy(AopProxy aopProxy) {
		return aopProxy.getProxy(this.proxyClassLoader);
	}

// 默认增强器转换适配器
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

	private final List<AdvisorAdapter> adapters = new ArrayList<>(3);

	public DefaultAdvisorAdapterRegistry() {
		registerAdvisorAdapter(new MethodBeforeAdviceAdapter());  // 前置通知适配器
		registerAdvisorAdapter(new AfterReturningAdviceAdapter()); // 返回通知适配器
		registerAdvisorAdapter(new ThrowsAdviceAdapter());         // 异常通知适配器
	}


	@Override
	public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        // 如果传入对象已经是增强器,直接返回(3.1.2直接使用增强器作为拦截器)
		if (adviceObject instanceof Advisor) {
			return (Advisor) adviceObject;
		}
		if (!(adviceObject instanceof Advice)) {
			throw new UnknownAdviceTypeException(adviceObject);
		}
		Advice advice = (Advice) adviceObject;
        // 方法拦截器,直接封装为DefaultPointcutAdvisor,增强器中的切点为匹配所有
		if (advice instanceof MethodInterceptor) {
			return new DefaultPointcutAdvisor(advice);
		}
        
        // 根据支持的适配器转换
		for (AdvisorAdapter adapter : this.adapters) {
			if (adapter.supportsAdvice(advice)) {
				return new DefaultPointcutAdvisor(advice);
			}
		}
		throw new UnknownAdviceTypeException(advice);
	}

	@Override
	public void registerAdvisorAdapter(AdvisorAdapter adapter) {
		this.adapters.add(adapter);
	}
}

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (!NativeDetector.inNativeImage() &&
				(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
			Class<?> targetClass = config.getTargetClass();
			// ... 省略部分代码
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);  //JDK的动态AOP代理
			}
			return new ObjenesisCglibAopProxy(config); // CGLIB的动态代理
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}


	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

}

3.1.4 JdkDynamicAopProxy 执行

   使用JDK动态代理时, 执行bookService.create("小白学习aop:代理bean")时,实际执行的时JdkDynamicAopProxy的invoke方法:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    // .. 省略部分代码

	private final AdvisedSupport advised; // 存储的是ProxyFactoryBean对象

	private final Class<?>[] proxiedInterfaces; // 代理的接口


	@Override
    // 获取代理对象
	public Object getProxy() {
		return getProxy(ClassUtils.getDefaultClassLoader());
	}

	@Override
	public Object getProxy(@Nullable ClassLoader classLoader) {
		if (logger.isTraceEnabled()) {
			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
		}
		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
	}

	@Override
	@Nullable
	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;

			// .. 省略部分代码
			target = targetSource.getTarget();
			Class<?> targetClass = (target != null ? target.getClass() : null);

			// 获得拦截器链,先查看方法对应的缓存是否有拦截器链,如果没有,通过增强器链工厂和method、adviece链表生成拦截器链,并存储方法对应的缓存
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

			if (chain.isEmpty()) {
				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
			}
			else {
                // 根据拦截器链和目标类、调用方法进行反射调用
				MethodInvocation invocation =
						new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
				retVal = invocation.proceed();
			}

		   // 省略部分代码
	}

  // .. 省略部分代码
}

3.2 BeanNameAutoProxyCreator 指定拦截器和需要AOP代理的bean进行自动代理

     BeanNameAutoProxyCreator可以指定拦截器(通知/增强器)以及需要进行代理的bean名称,对bean自动生成代理对象。BeanNameAutoProxyCreator继承了BeanPostProcessor接口,在bean后置处理器中,如果发现自己需要进行AOP代理,则从指定的通知/增强器中,查找能用于当前类的通知/增强器,生成代理对象,取代目标对象。

public class Springboot001Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Springboot001Application.class, args);

        // bookService已经是代理对象
        BookService bookService = (BookService)run.getBean("bookServiceImp");
        bookService.create("小白学习aop:原始bean");
    }

    @Bean
    public NameMatchMethodPointcutAdvisor bookServiceBeforeAdvisor(Advice logBeforeAdvice) {
        NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(logBeforeAdvice);
        advisor.setMappedName("create"); // 匹配create方法
        return advisor;
    }

    @Bean
    public NameMatchMethodPointcutAdvisor bookServiceAfterReturnAdvisor(Advice logAfterReturningAdvice) {
        NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(logAfterReturningAdvice);
        advisor.setMappedName("create"); // 匹配create方法
        return advisor;
    }

    @Bean
    public BeanNameAutoProxyCreator bookServiceProxy() {
        BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();

        // 使用增强器作为拦截器
        beanNameAutoProxyCreator.setInterceptorNames("bookServiceBeforeAdvisor", "bookServiceAfterReturnAdvisor");

        // 设置需要生成AOP代理的bean name,可以使用通配符*
        beanNameAutoProxyCreator.setBeanNames("*ServiceImp");

        return beanNameAutoProxyCreator;
    }

}

执行结果:

3.3 DefaultAdvisorAutoProxyCreator

   DefaultAdvisorAutoProxyCreator比BeanNameAutoProxyCreator,会对所有的bean查看是否需要生成AOP代理对象。在bean后置处理器中,查询到bean工厂中所有的增强器,如果有能用于当前类的AOP代理对象(PointCut能匹配当前类或者类中的某些方法),则使用这些增强器生成代理对象。

@SpringBootApplication
public class Springboot001Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Springboot001Application.class, args);

        // bookService已经是代理对象
        BookService bookService = (BookService)run.getBean("bookServiceImp");
        bookService.create("小白学习aop:原始bean");
    }

    @Bean
    public NameMatchMethodPointcutAdvisor bookServiceBeforeAdvisor(Advice logBeforeAdvice) {
        NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(logBeforeAdvice);
        advisor.setMappedName("create"); // 匹配create方法
        return advisor;
    }

    @Bean
    public NameMatchMethodPointcutAdvisor bookServiceAfterReturnAdvisor(Advice logAfterReturningAdvice) {
        NameMatchMethodPointcutAdvisor advisor = new NameMatchMethodPointcutAdvisor(logAfterReturningAdvice);
        advisor.setMappedName("create"); // 匹配create方法
        return advisor;
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator bookServiceProxy() {
        return new DefaultAdvisorAutoProxyCreator();
    }
}

4、通过注解开发

@EnableAspectJAutoProxy开启AOP,注解中improt AspectJAutoProxyRegistrar。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
	boolean proxyTargetClass() default false;

	boolean exposeProxy() default false;

}

AspectJAutoProxyRegistrar中注册了AnnotationAwareAspectJAutoProxyCreator bean,改aop自动代理创建器的执行过程和DefaultAdvisorAutoProxyCreator类似,在bean的后置处理器处理过程中,查找可用的advisors并生成代理对象。在查找可用的advisor时,会查找Aspect注解的切面类并创建增强器advisor对象。

	@Override
    // 注入beanFactory时执行(实现BeanFactoryAware接口)
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		if (this.aspectJAdvisorFactory == null) {
            // 设置增强器生成工厂
			this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
		}
        
        // 设置增强器构建适配器
		this.aspectJAdvisorsBuilder =
				new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
	}


	@Override
    // 查找候选advisors
	protected List<Advisor> findCandidateAdvisors() {
		List<Advisor> advisors = super.findCandidateAdvisors();
		if (this.aspectJAdvisorsBuilder != null) {
            // buildAspectJAdvisors会查找所有注解创建的advisors(解析含有Aspect注解的bean定义)
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

参考文章:https://www.cnblogs.com/xxkj/p/14094203.html

spring 5参考指南:https://docs.flydean.com/spring-framework-documentation5/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值