AOP动态代理注解
概念: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是包名,这个东西很重要,怕是注意不要写错了。还有我可能把之前的前置,后置的那个注解注释了,是为了不影响后面的测试,如果你多个一起使用的时候要注意,特别是抛出跟其他的一起使用。