java之aop
1.AOP:aspect orientied programming 面向切面编程。就是横向编程。
2.面向切面编程是在不改变原有代码的情况下增加新的功能。
3.在spring中面向切面编程有两种应用:
a) 声明式事务
b) 自定义aop编程
4.spring 提供了aop的相关概念及api :
切面(Aspect) : 一个关注点的模块化,这个关注点可能会横切多个对象。
连接点 (Joinpoint) : 在程序执行过程中某个特定的点,在Spring AOP 中,一个连接点总是表示一个方法的执行。
通知 (Advice) : 在切面的某个特定的连接点上执行的动作。
切入点( Pointcut) : 匹配连接点的断言。
目标对象(Target Object): 被一个或多个切面所通知的对象。
AOP 代理(AOP Proxy):AOP代理可以是JDK动态代理或者CGLIB代理。
织入(Weaving) : 把切面连接到其他应用程序类型或者对象上,并创建一个被通知的对象。
5.通知的类型
a) 前置通知(Before advice) : 在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。
b) 后置通知(After returning advice): 在某连接点正常完成后执行的通知;例如,一个方法没有抛出任何异常,正常返回。
c) 异常通知(After throwing advice) : 在方法抛出异常退出时执行的通知(不论正常返回还是异常退出)。
d) 环绕通知(Around Advice): 包围一个连接点的通知,如方法调用。
6.使用spring提供的api进行 aop 的开发
a) 新建 java 项目
b) 导入 jar 包
aopalliance.jar
aspectjweaver.jar
commons-logging.jar
spring-aop-4.1.6.RELEASE.jar
spring-aspects-4.1.6.RELEASE.jar
spring-beans-4.1.6.RELEASE.jar
spring-context-4.1.6.RELEASE.jar
spring-core-4.1.6.RELEASE.jar
spring-expression-4.1.6.RELEASE.jar
spring-tx-4.1.6.RELEASE.jar
c) 编写相关类
LogAdvice.java
/** * * 实现一个公共的日志业务,该业务实现了spring提供的前置通知 */ public class LogAdvice implements MethodBeforeAdvice{ @Override public void before(Method method, Object[] args, Object target) throws Throwable { System.out.println(target.getClass().getSimpleName()+":"+method.getName()+"方法被执行"); } }
UserServiceImpl.java
/** * 在service的方法中,经常会有一些公共的功能, * 如:事务,日志,权限,缓存等 * */ public class UserServiceImpl implements UserService{ @Override public void add() { System.out.println("add"); } @Override public void delete() { System.out.println("delete"); } @Override public void update() { System.out.println("update"); } }
d) 编写配置文件
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" 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="logAdvice" class="cn.sxt.aop.LogAdvice"/> <!-- 这是真实对象 --> <bean id="userService" class="cn.sxt.service.impl.UserServiceImpl"/> <!-- 使用spring的aop配置 将公共业务和真实对象联系起来 以前这个动作需要通过实现动态代理来完成,spring将动态代理 封装好了,只需要通过指定配置来完成即可 --> <aop:config> <aop:pointcut expression="execution(* cn.sxt.service.impl.*.*(..))" id="pointcut"/> <aop:advisor advice-ref="logAdvice" pointcut-ref="pointcut"/> </aop:config> </beans>
e) 测试
public class AopTest { @Test public void testBeforeAdvice(){ ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml"); UserService us = (UserService)ac.getBean("userService"); us.add(); } }
7. spring提供了一种 无侵入性 的 aop 实现
通知的代码
/** * * 实现一个公共的日志业务 */ public class LogAdvice{ public void log(){ System.out.println("-----相关日志信息----"); } }
配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" 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="logAdvice" class="cn.sxt.aop.LogAdvice"/> <!-- 这是真实对象 --> <bean id="userService" class="cn.sxt.service.impl.UserServiceImpl"/> <!-- 使用spring的aop配置 将公共业务和真实对象联系起来 以前这个动作需要通过实现动态代理来完成,spring将动态代理 封装好了,只需要通过指定配置来完成即可 --> <aop:config> <aop:pointcut expression="execution(* cn.sxt.service.impl.*.*(..))" id="pointcut"/> <aop:aspect ref="logAdvice"> <!-- 配置前置通知 --> <aop:before method="log" pointcut-ref="pointcut"/> </aop:aspect> </aop:config> </beans>
8. 通过注解来实现 aop
通知
/** * * 实现一个公共的日志业务 */ @Aspect public class LogAdvice{ @Before("execution(* cn.sxt.service.impl.*.*(..))") public void log(){ System.out.println("-----相关日志信息----"); } }
配置中,使用自动配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" 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="logAdvice" class="cn.sxt.aop.LogAdvice"/> <!-- 这是真实对象 --> <bean id="userService" class="cn.sxt.service.impl.UserServiceImpl"/> <!-- 使用注解来实现aop --> <aop:aspectj-autoproxy/> </beans>