什么是AOP?
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译形式和运行期动静代理实现程序性能的对立保护的一种技术。AOP是OOP的连续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP能够对业务逻辑的各个局部进行隔离。从而使得业务逻辑各个局部之间的耦合性升高,进步程序的可重用性,同时进步了开发的效率。
AOP在Spring中的作用
提供申明式事务;容许用户自定义切面
- 横切关注点:逾越应用程序多个模块的办法或性能。即是,与咱们的业务逻辑无关的,然而咱们须要关注的局部,就是横切关注点。如日志,平安,缓存,事务等等。
- 切面(ASPECT):横切关注点 被模块化 的非凡对象。 即 它是一个类。【Log】
- 告诉(Advice):切面必须要实现的工作。即 它是类中的一个办法。【Log中的办法】
- 指标(Target):被告诉对象。
- 代理(Proxy):向指标对象利用告诉之后创立的对象。
- 切入点(PointCut):切面告诉执行的“地点”的定义。
- 连接点(JointPoint):与切入点匹配的执行点。
SpringAOP中,通过Advice定义横切逻辑,Spring中反对5种类型的Advice:
即Aop在不扭转原有代码的状况下,去减少新的性能。
应用Spring实现AOP
应用AOP织入,须要导入一个依赖包
<dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.4</version> </dependency></dependencies>
- 形式一:应用Spring的API接口【SpringAPI接口实现】
applicationContext.xml:
<!--形式一:应用原生Spring API接口--><!--配置aop:须要导入aop的束缚--><aop:config> <!--切入点:expression:表达式,execution(要执行的地位)--> <aop:pointcut id="pointcut" expression="execution(* com.sunfl.service.UserServiceImpl.*(..))"/> <!--执行盘绕减少--> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/></aop:config>
日志类:
public class Log implements MethodBeforeAdvice { //method:要执行的指标对象的办法 //objects:参数 //target:指标对象 public void before(Method method, Object[] objects, Object target) throws Throwable { System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了"); }}public class AfterLog implements AfterReturningAdvice { //returnValue:返回值 public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { System.out.println("执行了"+method.getName()+"办法,返回后果为:"+returnValue); }}
测试后果:
com.sunfl.service.UserServiceImpl的add被执行了减少了一个用户执行了add办法,返回后果为:null
- 形式二:自定义来实现AOP【切面定义】
applicationContext.xml:
<bean id="diy" class="com.sunfl.diy.DiyPointCut"/><aop:config> <!--自定义切面:ref 要援用的类--> <aop:aspect ref="diy"> <!--切入点--> <aop:pointcut id="point" expression="execution(* com.sunfl.service.UserServiceImpl.*(..))"/> <!--告诉--> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect></aop:config>
自定义切入点:
public class DiyPointCut { public void before(){ System.out.println("=========办法执行前========"); } public void after(){ System.out.println("=========办法执行后========"); }}
测试后果:
=========办法执行前========减少了一个用户=========办法执行后========
- 形式三:应用注解实现
applicationContext.xml:
<!--形式三--><bean id="annotationPointCut" class="com.sunfl.diy.AnnotationPointCut"/><!--开启注解反对--><aop:aspectj-autoproxy/>
切面类:
@Aspect //标注这个类是一个切面public class AnnotationPointCut { @Before("execution(* com.sunfl.service.UserServiceImpl.*(..))") public void before(){ System.out.println("=======办法执行前======"); } @After("execution(* com.sunfl.service.UserServiceImpl.*(..))") public void after(){ System.out.println("=======办法执行后======"); } //在盘绕加强中,咱们能够给定一个参数,代表咱们要取得解决切入的点 @Around("execution(* com.sunfl.service.UserServiceImpl.*(..))") public void around(ProceedingJoinPoint jp) throws Throwable { System.out.println("盘绕前"); Signature signature = jp.getSignature();//取得签名 System.out.println("signature:"+signature); //执行办法 Object proceed = jp.proceed(); System.out.println("盘绕后"); System.out.println(proceed); }}
测试后果:
盘绕前signature:void com.sunfl.service.UserService.add()=======办法执行前======减少了一个用户盘绕后null=======办法执行后======