概念:AOP:可以在不动之前代码的前提下加入某些东西 动态:就是类似于公共类,你想用就调,很灵活 注解:例如:@Before,它是由我们aop jar包提供的
我们就通过注解来实现动态代理:主要还是看代码,学会用,在去深究它
logAdvice(写动态代理的这个类):
package spring; import java.util.Arrays; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; /* * AOP动态代理——注解 * 1、导入:aopalliance-1.0-jar、aspectjweaver-1.8.0.M1.jar * 2、了解切面编程思想(可以在某个方法的前面或者后加入东西,且不动之前的代码个人理解) * 切面(ascpet)=切入点(pointCut)+通知(advice) * 切入点(pointCut):@Pointcut修饰,修饰的方法不需要返回值,不需要参数,仅做为一个切入点的标记 * * 3、通知:(advice) * 前置通知:@Before修饰,在调用方法之前调用的代码 * 后置通知:@AfterReturning修饰,在调用方法之后调用的代码 * 环绕通知:@around修饰,在调用方法之前,以及方法调用完成之后执行的代码 * 抛出通知:@AfterThrowing修饰,在抛出异常之后调用的代码 * 前置通知:@After修饰,无论代码执行是否正常,它都会执行 */ /* * 切入点(pointCut): 修饰的方法不需要返回值,不需要参数,仅作为一个切入点的标记 */ @Aspect public class LogAdvice { @Pointcut("execution(* spring.*.select*(..)) || execution(* spring.*.insert*(..))") //指定所有包里面的带有某一个字样的某种方法:("execution(* spring.*.select*(..))")“..”一个点代表一个参数,两个代表任意个参数,Spring前面的*表示的是public、private等。你也可以换成你想要的 //指定某一个:("execution(* spring.UserDaoImpl.selectUser())") //如果需要指定多个在其后面:("execution(* spring.*.select*(..)) || * spring.*.insert*(..))") public void method() {} //1、前置通知: //@Before("method()")//在调用方法之前执行的代码 public void logBefore() { System.out.println("日志记录。。。。。前置通知【调用方法之前执行的代码】,例如权限控制"); } //@Before("method() && args(param)")//带参数,对参数进行校验 public void logBeforeWithParams(String param) { System.out.println("日志记录。。。。。前置通知【调用方法之前执行的代码】,例如权限控制:"+param); } //2、后置通知: //@AfterReturning(pointcut="method()",returning="returnValue") public void logAfterReturning(boolean returnValue) { System.out.println("日志记录。。。后置通知【调用方法之后执行的代码】,对返回值进行校验"+returnValue); } //3、环绕通知: @Around("method()") public Object logAround(ProceedingJoinPoint pjp) { try { System.out.println("日志记录。。。环绕通知【调用方法之后执行的代码】,例如:日志记录、事务管理...调用方法的对象"+pjp.getTarget().getClass().getName()); System.out.println("日志记录。。。环绕通知【调用方法之后执行的代码】,例如:日志记录、事务管理...调用方法传递的参数"+Arrays.toString(pjp.getArgs())); System.out.println("日志记录。。。环绕通知【调用方法之后执行的代码】,例如:日志记录、事务管理...调用方法名称"+pjp.getSignature().getName()); //调用正在的方法 Object returnValue= pjp.proceed(); System.out.println("日志记录。。。环绕通知【调用方法之后执行的代码】,例如:日志记录、事务管理"); return returnValue; } catch (Throwable e) { e.printStackTrace(); } return null; } //4、抛出通知: @AfterThrowing(pointcut = "method()",throwing = "ex") public void logAfterThrowing(Exception ex) { System.out.println("抛出通知:例如:日志文件、发送异常信息、发邮局、短信等....异常信息:"+ex.getMessage()); } //5、最终通知: @After("method()") public void logAfter() { System.out.println("最终通知。。。无论代码执行是否正常,它都会执行。。。例如:资源释放"); } }applicationContext.xml(开启aop注解功能这里主要的作用,还有声明我们要使用的bean):
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <bean id="userDao1" class="spring.UserDaoImpl"></bean> <bean id="userDao2" class="spring.UserDaoImpl_2"></bean> <bean id="logAdvice" class="spring.LogAdvice"></bean> <!-- 开启aop注解功能:生成自动代理 --> <aop:aspectj-autoproxy/> </beans>其中的UserDaoImpl跟UserDaoImpl只是在里面随便写了一个方法,放了几句输出,用来测试,自己写一下,下面一个是test:
package spring; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { //加载解析applicationContext.xml //积极加载,在加载与解析xml的同时,即完成所有bean的实例化 ClassPathXmlApplicationContext factory=new ClassPathXmlApplicationContext("applicationContext.xml"); System.out.println("IOC容器加载完成"); UserDaoImpl userDao=(UserDaoImpl)factory.getBean("userDao1"); userDao.insertUser("软件大哥大"); } }注意:前面的切入点的路径:就是你需要加入某些东西的路径,里面Spring是包名,这个东西很重要,怕是注意不要写错了。还有我可能把之前的前置,后置的那个注解注释了,是为了不影响后面的测试,如果你多个一起使用的时候要注意,特别是抛出跟其他的一起使用。