Spring AOP demo

发布时间 2023-04-16 12:48:49作者: min。

动态代理模式实现,

比如可以在Bean的生命周期创建阶段,根据Pointcut判断当前bean是否满足切入条件,如果满足,再根据织入器ProxyFactory织入到JoinPoint,再根据bean创建代理对象

名词

  • JoinPoint: 可以理解成系统中每一个可以应用aop的点,一般是指方法。spring中只支持方法,
  • Pointcut: 根据Pointcut的描述,可以定位到一批或者一个具体的JoinPoint
  • Advice:对JoinPoint要干的事情,before,afterreturning,afterthrowing,around
  • aspect: 整合了PointCut和Advice。

spring的advisor其实就是一个aspect,一个切面的两个关键点,Pointcut和Advice。

package aopdemo;

import org.springframework.aop.Advisor;
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.Pointcut;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.NameMatchMethodPointcut;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

/**
 * @author wenxiangmin
 * @ClassName AppConfig.java
 * @Description TODO
 * @createTime 2023年04月15日 14:53:00
 */
@Configuration
@ComponentScan(value = {"aopdemo"})
public class AppConfig {

	/**
	 * 切入点
	 * @return
	 */
	@Bean
	public Pointcut nameMatchMethodPointcut() {
		NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
		pointcut.setMappedName("insert*"); //方法名匹配
		return pointcut;
	}

	@Bean
	public BeforeAdvice beforeAdvice() {
		return new TestBeforeMethodAdvice();
	}

	/**
	 * advisor,设置切入点和通知
	 * @return
	 */
	@Bean
	public Advisor defaultAdvosor() {
		DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
		defaultPointcutAdvisor.setPointcut(nameMatchMethodPointcut());
		defaultPointcutAdvisor.setAdvice(beforeAdvice());
		return defaultPointcutAdvisor;

	}

	/**
	 * 前置通知
	 */
	class TestBeforeMethodAdvice implements MethodBeforeAdvice{
		@Override
		public void before(Method method, Object[] args, Object target) throws Throwable {
			System.out.println("before方法执行。methodName="+method.getName());
		}
	}

	/**
	 * 织入器
	 * 一个factoryBean,实际的对象类型是getObject方法返回的类型,也就是在getObject方法中生成的代理对象
	 * @return
	 */
	@Bean
	public ProxyFactoryBean taskService() {
		ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
		proxyFactoryBean.addAdvisor(defaultAdvosor());
		proxyFactoryBean.setInterceptorNames("insert*");
		proxyFactoryBean.setTargetName("taskServiceImpl");
		return proxyFactoryBean;
	}
}


		AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
		TaskServiceImpl taskService = (TaskServiceImpl)ctx.getBean("taskService");
		taskService.insert();

//输出
before方法执行。methodName=insert
insert exec...