什么是AOP
AOP(Aspect Oriented Programming 面向切面编程)是一种通过运行期动态代理实现代码复用的机制,是对传统OOP(Object Oriented Programming,面向对象编程 )的补充。目前,Aspectj是Java社区里最完整最流行的AOP框架,在Spring 2.0以上版本中可以通过Aspectj注解或基于XML配置AOP。
AOP中相关概念
一、注解实现
CalculatorService源码:
@Service
public class CalculatorService implements ICalculatorService {
public int mul(int a, int b) {
return a*b;
}
public int div(int a, int b) {
return a/b;
}
public String print() {
return "";
}
}
需要在xml中写入:
<context:component-scan base-package="com.jd"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
扫描com.jd包下的所有类,根据注解创建对象,放在IOC容器中。
配置自动代理。
切面类CalculatorAspect源码:
@Aspect
@Component
public class CalculatorAspect {
@Pointcut("execution(public int com.jd.calculator.service.CalculatorService.*(..))")
public void pointcut() {
}
//前置增强
@Before("pointcut()")
public void b(JoinPoint jp) {
Object [] args = jp.getArgs();
for (Object object : args) {
System.out.println(object);
}
Signature signature = jp.getSignature();
String name =signature.getName();
System.out.println(name);
System.out.println("The "+name+" method begins");
System.out.println("The "+name+" method args:["+ args[0] +","+ args[1]+"]");
}
}
使用main方法对其进行测试:
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
//执行该行代码时创建IOC容器,由于CalculatorService类中方法与CalculatorAspect切面类中切入点表
//所以默认情况下IOC自动为CalculatorService类创建代理类并创建相应的代理对象,
//如果采用懒加载方式创建CalculatorService对象,则在获取对象时自动为该对象创建代理对象。
ICalculatorService calculatorService = applicationContext.getBean(ICalculatorService.class);
System.out.println(calculatorService.getClass());
System.out.println(calculatorService.div(2, 2));
calculatorService.print();
applicationContext.close();
}
}
AOP实现的大致流程即为
- 将目标方法的类通过@Service注册到Spring容器管理,以便之后生成代理对象
- 通过@Aspect声明切面类,然后@component放入spring容器中
- 通过@增强(“execution(public 返回值 地址.*(…))”)建立切面
- 在ClassPathXmlApplicationContext applicationContext =new ClassPathXmlApplicationContext(“app.xml”);代码执行时创建IOC容器,@Service标注的类中方法与@Aspect@component标注的切面类中切入点表达式匹配,默认情况下IOC自动为@Service标注的类创建代理类并创建相应的代理对象,之后通过applicationContext.getBean(class);得到该类即可操作。
代码注解释义
- @Aspect//将该类声明为切面类
- @Component//将该类对象放入IOC容器
- @Service//将这个类在扫描时注册到Spring容器管理
- @Before(“execution(public int com.jd.calculator.service.CalculatorService.*(…))”):前置增强(又称前置通知)即在目标方法执行之前执。
二、XML配置实现
可在上述的注解方法中,删除相关的注解,删去之前的xml中的自动代理配置代码,在xml文件中写入以下代码:
<bean id="calculatorAspect" class="com.jd.calculator.CalculatorAspect"></bean>
<!-- 配置AOP -->
<aop:config proxy-target-class="true">
<!-- 配置切点表达式 -->
<aop:pointcut expression="execution(public int com.jd.calculator.CalculatorService.*(..))" id="pointcut"/>
<!-- 配置切面及增强类型:可以有多个切面,每个切面又可以配置多个增强类型-->
<aop:aspect ref="calculatorAspect">
<aop:before method="before" pointcut-ref="pointcut"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
<aop:after method="after" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
再次使用test进行测试即可。