spring的 aop:
aop:面向方面的编程,面向切面的编程,面向横切的编程
方面就是新的业务功能,
把新的方面的功能横切到老的业务的前或后
spring的aop的底层用的是动态代理
如果目标类有接口就默认用jdk动态代理
如果目标类没有接口就用默认cglib动态代理
如果目标类有接口且不是final的,还想用cglib动态代理则需要单独配置
spring aop中定义个一套独有的表达式规则用于指定某些业务方法横切新功能
实现spring aop的步骤:
1.创建一个工程 工程是基础
2.导入jar包 spring的功能基础
spring的基础jar
spring-context.jar
spring-core.jar
spring-beans.jar
spring-expression.jar
commons-logging.jar
spring aop的jar
spring-aop.jar
aspectjweaver-1.8.7.jar
aopalliance-1.0.jar
3.创建java类
老的业务类:
UserDao.java UserDaoImpl.java
UserService.java UserServiceImpl.java
新的业务功能/新方面的功能/新的切面的功能,简称为方面/切面
由动态代理创建代理类用于调用接口方法,在接口方法中耦合切面和老业务功能
4.创建spring的配置文件
springaop的xml版本
springaop的annotation版本
无论是xml版本还是注解版本
a.实例化老业务和新业务的对象(ioc)
b.根据业务需求,设定对象的注入关系(di)
c.写spring的特有的表达式规则,用于指定哪些方法需要横切新的功能<aop:XXX>
5.启动spring的容器读取spring的配置文件
6.从spring容器中取出对应的对象备用
xml版本:
新业务功能:
TransactionManager.java
/**
* 此类是一个新功能类,用于给原有业务添加事务处理的功能
* 符合单一职责原则,此类只做事务管理
* @author Administrator
*
*/
public class TransactionManager {
/**
* 事务的开启
* 在前置通知方法中得到目标的参数及其他信息
*/
public void begin(JoinPoint joinPoint){
System.out.print("事务开启");
System.out.println("目标方法的参数:"+joinPoint.getArgs()[0].getClass());
User user=(User)joinPoint.getArgs()[0];
System.out.println("目标方法的参数的值:"+user.getName()+" "+user.getPassword());
System.out.println("目标方法的名称:"+joinPoint.getSignature().getName());
System.out.println("调用目标方法的目标对象"+joinPoint.getTarget().getClass());
}
/**
* 事务提交
* 在后置通知中得到目标方法的参数及其他信息,还可以得到目标方法的返回值
* 注意:如果有JoinPoint joinPoint参数一定要放参数的第一个位置
*/
public void commit(JoinPoint joinPoint,Object returnValue){
System.out.println("事务提交");
System.out.println("目标方法的返回值:"+returnValue);
}
/**
* 事务的回滚
* 在异常通知中得到目标方法的参数及其他信息,不能得到目标方法的返回值,但能得到异常信息
*/
public void rollback(JoinPoint joinPoint,Throwable ex){
System.out.println("事务回滚");
System.out.println("目标方法的异常信息:"+ex.getMessage());
}
public void finalMethod(JoinPoint joinPoint){
System.out.println("finally");
}
/**
* 环绕通知,可以完全替换前4个通知
* 用环绕通知有一个最大的好处,能够控制目标方法的执行
* @param pjp
* @return
* @throws Throwable
*/
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object retVal =null;
try{
//前置通知
System.out.println("前置通知");
System.out.println("目标方法的参数:"+pjp.getArgs()[0].getClass())