转载

Spring框架04-AOP应用

Spring AOP 应⽤

AOP本质:在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是权限校验代码、⽇志代    码、事务控制代码、性能监控代码。

1 节 AOP相关术语

1.1业务主线

在讲解AOP术语之前,我们先来看⼀下下⾯这两张图,它们就是第三部分案例需求的扩展(针对这些扩    展的需求,我们只进⾏分析,在此基础上去进⼀步回顾AOP,不进⾏实现)

上图描述的就是未采⽤AOP思想设计的程序,当我们红⾊框中圈定的⽅法时,会带来⼤量的重复劳动。    程序中充斥着⼤量的重复代码,使我们程序的独⽴性很差。⽽下图中是采⽤了AOP思想设计的程序,它    把红框部分的代码抽取出来的同时,运⽤动态代理技术,在运⾏期对需要使⽤的业务逻辑⽅法进⾏增强。

1.2AOP术语

名词

解释

Joinpoint( 连接点 )

它指的是那些 可以 ⽤于把增强代码加⼊到业务主线中的点,那么由上图中我们可    以看出,这些点指的就是⽅法。在⽅法执⾏的前后通过动态代理技术加⼊增强的   代码。在Spring框架AOP思想的技术实现中,也只⽀持⽅法类型的连接点。

Pointcut(

⼊点 )

它指的是那些已经把增强代码加⼊到业务主线进来之后的连接点。由上图中,我   们看出表现层 transfer⽅法就只是连接点,因为判断访问权限的功能并没有对其增强。

Advice( / 增强 )

它指的是切⾯类中⽤于提供增强功能的⽅法。并且不同的⽅法增强的时机是不⼀  样的。⽐如,开启事务肯定要在业务⽅法执⾏之前执⾏;提交事务要在业务⽅法  正常执⾏之后执⾏,⽽回滚事务要在业务⽅法执⾏产⽣异常之后执⾏等等。那么  这些就是通知的类型。其分类有: 前置通知 后置通知 异常通知 最终通知 环绕通

Target( ⽬标 对象 )

它指的是代理的⽬标对象。即被代理对象。

Proxy( 代理 )

它指的是⼀个类被AOP织⼊增强后,产⽣的代理类。即代理对象。

Weaving(

)

它指的是把增强应⽤到⽬标对象来创建新的代理对象的过程。spring采⽤动态代 理织⼊,⽽AspectJ采⽤编译期织⼊和类装载期织⼊。

Aspect(

)

它指定是增强的代码所关注的⽅⾯,把这些相关的增强代码定义到⼀个类中,这    个类就是切⾯类。例如,事务切⾯,它⾥⾯定义的⽅法就是和事务相关的,像开    启事务,提交事务,回滚事务等等,不会定义其他与事务⽆关的⽅法。我们前⾯   的案例中 TrasnactionManager就是⼀个切⾯。

连接点:⽅法开始时、结束时、正常运⾏完毕时、⽅法异常时等这些特殊的时机点,我们称之为连接     点,项⽬中每个⽅法都有连接点,连接点是⼀种候选点

切⼊点:指定AOP思想想要影响的具体⽅法是哪些,描述感兴趣的⽅法

Advice增强:

第⼀个层次:指的是横切逻辑

第⼆个层次:⽅位点(在某⼀些连接点上加⼊横切逻辑,那么这些连接点就叫做⽅位点,描述的是具体     的特殊时机)

Aspect切⾯:切⾯概念是对上述概念的⼀个综合Aspect切⾯= 切⼊点+增强

= 切⼊点(锁定⽅法) + ⽅位点(锁定⽅法中的特殊时机)+ 横切逻辑

众多的概念,⽬的就是为了锁定要在哪个地⽅插⼊什么横切逻辑代码

2 Spring AOP 的代理选择

Spring 实现AOP思想使⽤的是动态代理技术

默认情况下,Spring会根据被代理对象是否实现接⼝来选择使⽤JDK还是CGLIB。当被代理对象没有实现任何接⼝时,Spring会选择CGLIB。当被代理对象实现了接⼝,Spring会选择JDK官⽅的代理技术,不过我们可以通过配置的⽅式,让Spring强制使⽤CGLIB。

3 节 Spring AOP 的配置⽅式

在Spring的AOP配置中,也和IoC配置⼀样,⽀持3类配置⽅式。第⼀类:使⽤XML配置

第⼆类:使⽤XML+注解组合配置

第三类:使⽤纯注解配置

4 节 Spring AOP 实现

需求:横切逻辑代码是打印⽇志,希望把打印⽇志的逻辑织⼊到⽬标⽅法的特定位置(service层transfer

⽅法)

4.1XML模式

Spring是模块化开发的框架,使⽤aop就引⼊aop的jar

坐标

AOP 核⼼配置

细节

关于切⼊点表达式

上述配置实现了对 TransferServiceImpl的 updateAccountByCardNo⽅法进⾏增强,在其执⾏之前,输出了记录⽇志的语句。这⾥⾯,我们接触了⼀个⽐较陌⽣的名称: 切⼊点表达    ,它是做什么的呢?我们往下看。

概念及作⽤

切⼊点表达式,也称之为AspectJ切⼊点表达式, 指的是遵循特定语法结构的字符串,其 作⽤是⽤于对符合语法格式的连接点进⾏增强。 它是AspectJ表达式的⼀部分。

关于AspectJ

AspectJ是⼀个基于Java语⾔的AOP框架,Spring框架从2.0版本之后集成了AspectJ框架中切⼊点表达式的部分,开始⽀持AspectJ切⼊点表达式。

切⼊点表达式使⽤示例

改变代理⽅式的配置

在前⾯我们已经说了,Spring在选择创建代理对象时,会根据被代理对象的实际情况来选择  的。被代理对象实现了接⼝,则采⽤基于接⼝的动态代理。当被代理对象没有实现任何接⼝    的时候,Spring会⾃动切换到基于⼦类的动态代理⽅式。

但是我们都知道,⽆论被代理对象是否实现接⼝,只要不是final修饰的类都可以采⽤cglib提 供的⽅式创建代理对象。所以Spring也考虑到了这个情况,提供了配置的⽅式实现强制使⽤  基于⼦类的动态代理(即cglib的⽅式),配置的⽅式有两种

使⽤aop:config标签配置

使⽤aop:aspectj-autoproxy标签配置

五种通知类型

前置通知

配置⽅式: aop:before 标签

执⾏时机

前置通知永远都会在切⼊点⽅法(业务核⼼⽅法)执⾏之前执⾏。

细节

前置通知可以获取切⼊点⽅法的参数,并对其进⾏增强。

正常执⾏时通知

配置⽅式

异常通知

配置⽅式

执⾏时机

异常通知的执⾏时机是在切⼊点⽅法(业务核⼼⽅法)执⾏产⽣异常之后,异常通知执⾏。如果切

⼊点⽅法执⾏没有产⽣异常,则异常通知不会执⾏。

细节

异常通知不仅可以获取切⼊点⽅法执⾏的参数,也可以获取切⼊点⽅法执⾏产⽣的异常信息。

最终通知

配置⽅式

执⾏时机

最终通知的执⾏时机是在切⼊点⽅法(业务核⼼⽅法)执⾏完成之后,切⼊点⽅法返回之前执⾏。     换句话说,⽆论切⼊点⽅法执⾏是否产⽣异常,它都会在返回之前执⾏。

细节

最终通知执⾏时,可以获取到通知⽅法的参数。同时它可以做⼀些清理操作。

环绕通知

配置⽅式

4.2 XML+ 注解模式

XML 中开启 Spring 对注解 AOP 的⽀持

示例

*第⼀步:编写⼀个⽅法

*第⼆步:在⽅法使⽤@Pointcut注解

*第三步:给注解的value属性提供切⼊点表达式

*细节:

*1.在引⽤切⼊点表达式时,必须是⽅法名+(),例如"pointcut()"。

*2.在当前切⾯中使⽤,可以直接写⽅法名。在其他切⾯中使⽤必须是全限定⽅法名。

*/

@Pointcut("execution(* com.lagou.service.impl.*.*(..))") public void pointcut(){}

@Before("pointcut()")

public void beforePrintLog(JoinPoint jp){ Object[] args = jp.getArgs();

System.out.println("前置通知:beforePrintLog,参数是:"+

Arrays.toString(args));

}

@AfterReturning(value = "pointcut()",returning = "rtValue") public void afterReturningPrintLog(Object rtValue){

System.out.println("后置通知:afterReturningPrintLog,返回值

是:"+rtValue);

}

@AfterThrowing(value = "pointcut()",throwing = "e") public void afterThrowingPrintLog(Throwable e){

System.out.println("异常通知:afterThrowingPrintLog,异常是:"+e);

}

@After("pointcut()")

public void afterPrintLog(){ System.out.println("最终通知:afterPrintLog");

}

/**

*环绕通知

*@parampjp

*@return

*/ @Around("pointcut()")

public Object aroundPrintLog(ProceedingJoinPoint pjp){

//定义返回值

Object rtValue = null; try{

//前置通知

System.out.println("前置通知");

//1.获取参数

Object[] args = pjp.getArgs();

4.3注解模式

在使⽤注解驱动开发aop时,我们要明确的就是,是注解替换掉配置⽂件中的下⾯这⾏配置:

在配置类中使⽤如下注解进⾏替换上述配置

5 节 Spring声明式事务的⽀持

原文  https://segmentfault.com/a/1190000022550588
正文到此结束
Loading...