AOP(Aspect Oriented Programming 面向切面编程)是一种通过运行期动态代理实现代码复用的机制,是对传统OOP(Object Oriented Programming,面向对象编程 )的补充。目前,Aspectj是Java社区里最完整最流行的AOP框架,在Spring 2.0以上版本中可以通过Aspectj注解或基于XML配置AOP。
AOP的重要作用是增强对应的普通方法,提高方法中代码的复用性,具体场景可参考相关文章JDK动态代理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<context:component-scan base-package="com.jd"></context:component-scan>
<aop:aspectj-autoproxy proxy-target-class="false"></aop:aspectj-autoproxy>
</beans>
其中“context:component-scan”作用是扫描com.jd包下所有注解;
“aop:aspectj-autoproxy”作用是设置Spring自动为有@Aspect注解的对象产生动态代理对象,**proxy-target-class=“false”**为采用JDK动态代理,proxy-target-class="true"代表采用CGLib动态代理。
注意:
1、从Spring 3.2开始spring-core-xxx.jar包已集成CGLib和ASM 相关jar包,所以Spring工程不需再额外引入这些jar包;
2、即使proxy-target-class设置为false,如果目标类没有声明接口,则Spring将自动使用CGLib生成代理对象。
package com.zzu.calculator;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect//将该类声明为切面类
@Component
public class CalculatorAspect {
@Before("execution(public int com.jd.calculator.CalculatorService.mul(..))")
public void before(JoinPoint jp) {
Object obj = jp.getTarget();
Object[] args = jp.getArgs();
System.out.println(obj.getClass().getName()+":The mul method begins.");
System.out.println(obj.getClass().getName()+":Parameters of the mul method: ["+args[0]+","+args[1]+"]");
}
}
Before注解为前置增强,其中的参数为切入点表达式(“execution(public int com.jd.calculator.CalculatorService.mul(…))”),是在目标方法执行之前执行。
sevice层代码:
package com.zzu.calculator;
import org.springframework.stereotype.Service;
@Service
public class CalculatorService implements ICalculatorService {
@Override
public int mul(int a, int b) {
int result = a*b;
return result;
}
@Override
public int div(int a, int b) {
int result = a/b;
return result;
}
}
Test类
package com.zzu.test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.zzu.calculator.ICalculatorService;
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
ICalculatorService calculator = applicationContext.getBean(ICalculatorService.class);
int result = calculator.mul(4, 2);
System.out.println("——>"result);
applicationContext.close();
}
}
结果
com.jd.calculator.CalculatorService:The mul method begins.
com.jd.calculator.CalculatorService:Parameters of the mul method: [4,2]
——>8
@After("execution(public int com.jd.calculator.CalculatorService.mul(..))")
public void after(JoinPoint jp) {
Object target=jp.getTarget();
String methodName = jp.getSignature().getName();
System.out.println(target.getClass().getName()+":The "+methodName+" method ends.");
}
sevice类与Test类同上
执行结果
com.jd.calculator.CalculatorService:The mul method ends.
——>8
XML配置文件添加autoproxy标签
Spring寻找带有@Aspect的类,例如上面的CalculatorAspect类
扫描带有@Aspect的类中带有 @Before,@After,@AfterReturning,@Around,@AfterThrowing 等注解的方法,得到该注解,并根据不同的注解判断是对应的是哪一种增强方式
获取表达式,例如上面的(“execution(public int com.jd.calculator.CalculatorService.mul(…))”)这个表达式就是指定需要被增强的方法
检查Spring能扫描到的所有类,找到表达式匹配的方法对应的类
为该类创建动态代理对象