AOP简介
Aspect Oriented Programming
- 面向切面编程
AOP在Spring中的作用
- 提供声明式服务(declarative enterprise services),尤其是声明式事务(declarative transaction management)
- 允许用户实现自定义切面以完善OOP
AOP is used in the Spring Framework to:
1.provide declarative enterprise services, especially as a replacement for EJB declarative services. The most important such service is declarative transaction management.
2.allow users to implement custom aspects, complementing their use of OOP with AOP.
AOP编程
- 在运行时,将代码动态地切入到类的指定方法、指定位置上的编程思想
- 通过动态代理的方式实现
- 优点
- 能够专注于核心业务的处理
- 减少重复的代码
AOP关键概念
- 关注点
- concern
- 一系列的业务,例如: 日志、安全检查
- 切面
- aspect
- 一个关注点的模块化,这个关注点可能会横切多个
- 连接点
- join point
- 程序中方法的执行
- 通知
- advice
- 在切面上某个特定的连接点上执行的动作
- before advice: 前置通知
- after returning advice: 后置通知
- after throwing advice: 异常通知
- after (finally) advice: 最终通知
- around advice: 环绕通知
- 织入
- weaving
- 将切面连接到其他应用程序或者对象上,并创建一个通知对象
使用Spring实现AOP
通过Spring的API来实现AOP
- 配置文件中需要添加aop相关的头文件
before advice前置通知的实现
public class Log implements MethodBeforeAdvice{ /* * @param method being invoked(被调用的方法的方法对象) * @param arguments to the method(被调用方法的参数) * @param target of the method invocation(被调用方法的目标对象) */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName() + "'s " + method.getName() + "() is executed"); } }
after returning advice实现
public class AfterLog implements AfterReturningAdvice{ /** * 目标方法执行后执行的通知 * @param returnValue: 返回值 * @param method: 被调用的方法对象 * @param args: 方法参数 * @param target: 被调用的方法的目标对象 **/ @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getName() + "'s " + method.getName() + "has been executed successfully and return value is " + returnValue); } }
xml配置文件
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.eric.service.impl.UserServiceImpl"></bean> <bean id="log" class="com.eric.log.Log"></bean> <bean id="afterLog" class="com.eric.log.AfterLog"></bean> <aop:config> <!-- 切入点配置 expression: 表示切入点的执行方法 x.y.Class.*(): 表示所有方法都作为切入点 x.y.Class.method(..): 表示匹配所有传入参数的格式 *用于匹配所有的类/方法 ..用于匹配所有的参数格式 --> <aop:pointcut expression="execution(* com.eric.service.impl.*.*(..))" id="pointcut"/> <!-- 配置执行的公共业务 advice-ref: 执行的公共业务方法 pointcut-ref: 切入点的引用 --> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/> </aop:config> </beans>
测试类
public class Test { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml"); UserService userService = (UserService) ac.getBean("userService"); userService.add(10); userService.delete(); } }/*output: com.eric.service.impl.UserServiceImpl's add() is executed add com.eric.service.impl.UserServiceImpl's addhas been executed successfully and return value is null com.eric.service.impl.UserServiceImpl's delete() is executed delete com.eric.service.impl.UserServiceImpl's deletehas been executed successfully and return value is null */
自定义类实现AOP
切面
public class Log { public void before() { System.out.println("execute before method invocation"); } public void after() { System.out.println("execute after method invocation"); } }
配置文件
<bean id="userService" class="com.eric.service.impl.UserServiceImpl"></bean> <bean id="log" class="com.eric.log.Log"></bean> <aop:config> <!-- 引用切面 --> <aop:aspect ref="log"> <!-- 配置连接点 --> <aop:pointcut expression="execution(* com.eric.service.impl.*.*(..))" id="pointcut"/> <!-- 配置前置通知 --> <aop:before method="before" pointcut-ref="pointcut"/> <!-- 配置后置通知 --> <aop:after method="after" pointcut-ref="pointcut"/> </aop:aspect> </aop:config>
使用注解实现AOP
切面
//表示切面 @Aspect public class Log { @Before("execution(* com.eric.service.impl.*.*(..))") public void before() { System.out.println("execute before method invocation"); } @After("execution(* com.eric.service.impl.*.*(..))") public void after() { System.out.println("execute after method invocation"); } @Around("execution(* com.eric.service.impl.*.*(..))") public Object around(ProceedingJoinPoint jp) throws Throwable { System.out.println("---around before"); System.out.println("sign:" + jp.getSignature()); Object result = jp.proceed(); System.out.println("---around after"); return result; } }
配置文件
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.eric.service.impl.UserServiceImpl"></bean> <bean id="log" class="com.eric.log.Log"></bean> <aop:aspectj-autoproxy/> </beans>