Spring 学习笔记(十)- 基于注解的 Spring 的 AOP 代码实现试验

1. 添加 jar 包

<dependency>
    <groupId>aopalliance</groupId>
    <artifactId>aopalliance</artifactId>
    <version>1.0</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.0.6.RELEASE</version>
</dependency>

2. 写 Spring 的配置文件,把注解扫面打开,写接口和实现类,测试类

1. applicationContext.xml

<context:component-scan base-package="www.xq.spring"></context:component-scan>

2. 接口

public interface AopTest {
     public int add(int i,int j);
     public int sub(int i,int j);
}

3. 实现类

@Component
public class AopTestImpl implements AopTest {

	public int add(int i, int j) {
		int rs = i + j;
		System.out.println("add rs: " + rs);
		return rs;
	}

	public int sub(int i, int j) {
		int rs = i - j;
		System.out.println("sub rs: " + rs);
		return rs;
	}
}

4. 测试类

public class RunMain {
	public static void main(String[] args) {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
		AopTest aopTest = (AopTest) ctx.getBean("aopTestImpl");
		aopTest.add(1, 4);
		aopTest.sub(5, 1);
	}
}

3. 定义切面类,LoggerAspect

/**
 * 要让这个类为切面类
 * 1. 首先让其加入到 Spring 的 ioc 容器中去,加注解 @Component
 * 2. 其次要声明它是切面类,加注解 @Aspect
 * @author lenovo
 *
 */

@Aspect
@Component
public class LoggerAspect {
	
	Logger logger = Logger.getLogger(this.getClass());
	
	//定义切面方法,这里有一个关键,告诉 Spring,这个方法在哪个类方法前还是后切入,明确切入点
	//说白了,这个方法要在切入点被切入进去并执行
	@Before("execution(public int www.xq.spring.aop.AopTestImpl.add(int,int))")
	public void beforeMethod(JoinPoint joinPoint) {
		System.out.println("xxxx方法执行之前,记录日志");
	}
}

4. spring 的配置文件中,让 @Before 注解起作用

<!-- 
    让切面类里的方法上的注解起作用,具体什么作用呢:未被切入的类生产一个代理类(子类),
    代理类中加了切面类的方法,说白了,这个代理类,就偷梁换柱了 
-->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

可以看到在指定的切入点,切入了切面类的方法,讲分离的日志代码和业务代码在运行时合起来了!

5. 继续完善切面类

public class LoggerAspect {
	
	Logger logger = Logger.getLogger(this.getClass());
	
	//定义切面方法,这里有一个关键,告诉 Spring,这个方法在哪个类方法前还是后切入,明确切入点
	//说白了,这个方法要在切入点被切入进去并执行
	@Before("execution(public int www.xq.spring.aop.AopTestImpl.add(int,int))")
	public void beforeMethod(JoinPoint joinPoint) {
		//通过方法里加一个参数,链接点的对象,可以获取到切入点的那个方法的信息
		String methodName = joinPoint.getSignature().getName();//拿到方法名
		List<Object> args = Arrays.asList(joinPoint.getArgs());//拿到方法参数
		logger.info(methodName + "方法执行之前,记录日志!方法的参数" + args);
	}
	
}

6. 一个方法实现了,扩展到多个方法,用 * 代替 add 方法名,表示任意方法:

@Before("execution(public int www.xq.spring.aop.AopTestImpl.*(int,int))")

7. 运行结果

 2019-03-19 20:25:08,481 INFO [www.xq.spring.aop.LoggerAspect.beforeMethod(LoggerAspect.java:35)] add方法执行之前,记录日志!方法的参数[1, 4]  
  add rs: 5

 2019-03-19 20:25:08,483 INFO [www.xq.spring.aop.LoggerAspect.beforeMethod(LoggerAspect.java:35)] sub方法执行之前,记录日志!方法的参数[5, 1]  
  sub rs: 4

最后,对@Before注解在解释一下:

  1. @Before和它注解的这个方法在AOP里叫:通知(advice),这个我们除了@Before这个叫前置通知(在切入目标方法执行之前执行)外,还有:
  2. @After后置通知(在目标方法执行之后执行)
  3. @AfterReturning返回通知(在目标方法返回结果之后执行)
  4. @AfterThrowing异常通知(在目标方法跑出异常之后执行)
  5. @Around环绕通知(围绕着方法执行)

@Before注解后的括号的内容叫AspectJ表达式,这里还可进一步使用通配符*

//public int 换成 * : 任何修饰符和返回值类型
@Before("execution(int int www.xq.spring.aop.AopTestImpl.*(int,int))")
//AopTestImpl换成*,表示cn.ybzy.springdemo包里的所有类
@Before("execution(int int www.xq.spring.aop.*.*(int,int))")
//还可用两个点儿表示任意参数
@Before("execution(int int www.xq.spring.aop.*.*(*,*))")

很多个方法都是相同的切入点表达式,可以像提公因式样的提出来:

@Pointcut("execution(* www.xq.spring.aop.*.*(*,*))")
public void joinPointExpression() {}

@Before("joinPointExpression()")
public void beforeMethod(JoinPoint joinPoint) {
        ....
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值