spring学习(四)AOP

cglib代理

动态代理有个约束:目标对象一定是要有接口的,没有接口就不能实现动态代理…..----->因此出现了cglib代理

cglib代理也叫子类代理,从内存中构建出一个子类来扩展目标对象的功能!

  • CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)

写cglib代理步骤:

  • 需要引入cglib – jar文件, 但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。

  • 引入功能包后,就可以在内存中动态构建子类

  • 代理的类不能为final,否则报错【在内存中构建子类来做扩展,当然不能为final,有final就不能继承了】

  • 目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。

AOP

Aop: aspect object programming 面向切面编程

  • 功能: 让关注点代码(重复代码)与业务代码分离!

  • 面向切面编程就是指: 对很多功能都有的重复的代码抽取,再在运行的时候往业务方法上动态植入“切面类代码”。

步骤:

  • 1、引入aop相关jar文件 (aspectj aop优秀组件)

    • spring-aop-3.2.5.RELEASE.jar 【spring3.2源码】

    • aopalliance.jar 【spring2.5源码/lib/aopalliance】

    • aspectjweaver.jar 【spring2.5源码/lib/aspectj】或【aspectj-1.8.2lib】

    • aspectjrt.jar 【spring2.5源码/lib/aspectj】或【aspectj-1.8.2lib】

  • 2、bean.xml中引入aop声明

<beans
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
</beans>

注解:

  • @Aspect 指定一个类为切面类

  • @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式

    • Pointcut定义时,还可以使用&&、||、! 这三个运算

    @Pointcut("logSender() || logReceiver()")
    private void logMessage(){}
    • 还可以将一些公用的Pointcut放到一个类中,以供整个应用程序使用,在使用时,指定完整的类名加上Pointcut签名就可以了

    @Before("bean.Pointcuts.logMessage()")
    public void before() {
    }
  • @Before("pointCut_()") 前置通知: 目标方法之前执行

  • @After("pointCut_()") 后置通知:目标方法之后执行(始终执行)

  • @AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)

  • @AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行

  • @Around("pointCut_()") 环绕通知: 环绕目标方法执行,使用该注解的方法必须传入ProceedingJoinPoint对象,并调用它的proceed()方法(执行目标方法)

@Pointcut表达式解析 execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)throws-pattern?)

括号中各个pattern分别表示:

  • 修饰符匹配(modifier-pattern?),可省略不写

  • 返回值匹配(ret-type-pattern)可以为 * 表示任何返回值,全路径的类名等

  • 类路径匹配(declaring-type-pattern?),bean.* 表示bean包下的所有类

  • 方法名匹配(name-pattern)可以指定方法名,* 代表所有, set* 代表以set开头的所有方法

  • 参数匹配((param-pattern))可以指定具体的参数类型,多个参数间用 “,” 隔开,各个参数也可以用 “ * ” 来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(..)表示零个或多个任意参数

  • 异常类型匹配(throws-pattern?)

  • 其中后面跟着“?”的是可选项

@Component
@Aspect
public class AOP {
//定义切入点
   @Pointcut("execution(* bean.*.*(..))")
   public void pt(){}

//可以直接写切入点表达式
   @Before("execution(* bean.*.*(..))")
   public void before(){
       System.out.println("开始事务");
  }
   //使用定义好的切入点
   @After("pt()")
   public void after(){
       System.out.println("关闭事务");
  }

   @Around("pt()")
   public void around(ProceedingJoinPoint joinPoint) throws Throwable {
       System.out.println("环绕前...");
       //必须传入ProceedingJoinPoint对象,调用proceed()方法 来执行目标方法
       joinPoint.proceed();
       System.out.println("环绕后...");
  }
}

 

原文地址:https://www.cnblogs.com/yjh1995/p/14164346.html