Spring AOP
来源:互联网 发布:org.apache.tiles 编辑:程序博客网 时间:2024/05/16 01:19
AOP:面向切面编程,相对于OOP面向对象编程
Spring AOP使用动态代理技术在运行期织入增强的代码,Spring AOP使用了两种代理机制,一种是基于JDK的动态代理,另一种是基于CGLib的动态代理,之所以使用两种代理机制,很大程度是因为JDK本身只提供接口的代理,而不支持类的代理。
Demo:
新建一个注解类@interface Action:
package com.example.mavenspringmvc.annotation;import java.lang.annotation.*;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Action { String name();}
这里讲下注解:注解本身是没有功能的,就和xml一样,注解之一种元数据,即解释数据的数据,这就是所谓配置。注解的功能来自于用这个注解的地方
编写使用注解的被拦截类:AspectService.java
package com.example.mavenspringmvc.aspect;import org.springframework.stereotype.Service;import com.example.mavenspringmvc.annotation.Action;@Servicepublic class AspectService { @Action(name = "注解action的name属性") public void printHelloWorld(){ System.out.println("Hello World"); }}
编写使用方法规则被拦截类:TestAspectService.java
package com.example.mavenspringmvc.service.test;import org.springframework.stereotype.Service;@Servicepublic class TestAspectService { public void printOrderInfo(String orderID,String checkTime){ System.out.println("订单号: " + orderID + ", 复核时间: " + checkTime); }}
编写切面:LogAspect.java
package com.example.mavenspringmvc.aspect;import com.example.mavenspringmvc.annotation.Action;import org.apache.log4j.spi.LoggerFactory;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.stereotype.Component;import java.lang.reflect.Method;import java.util.logging.Logger;@Aspect //通过该注解声明一个切面@Component //通过@Component,让切面成为spring容器管理的beanpublic class LogAspect { @Pointcut("@annotation(com.example.mavenspringmvc.annotation.Action)") public void actionAnnotationPointCut(){} @After("actionAnnotationPointCut()") public void after(JoinPoint joinPoint){ //获取连接点的方法签名对象 MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature(); Method method = methodSignature.getMethod(); Action action = method.getAnnotation(Action.class); System.out.println("注解式拦截:" + action.name()); } @Before("execution(* com.example.mavenspringmvc.service.test.TestAspectService.*(..))") public void before(JoinPoint joinPoint){ MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature(); Method method = methodSignature.getMethod(); String methodName = method.getName(); Object[] argsArray = joinPoint.getArgs(); System.out.print("执行方法参数: "); for(Object o : argsArray){ System.out.print(o + ", "); } System.out.println(methodName); }}
代码解释:
通过@Aspect注解声明一个切面
通过@Component让此切面成为Spring容器管理的Bean
通过@PointCut注解声明切点
通过@After注解声明一个增强类型,并使用@PointCut定义的切点
编写配置类:AppConfig.java
package com.example.mavenspringmvc.config;import org.springframework.context.annotation.*;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;@Configuration@EnableAspectJAutoProxy(proxyTargetClass = true)@ComponentScan(basePackages = {"com.example.mavenspringmvc"})@Import({TaskExecutorConfig.class, ConditionConfig.class})public class AppConfig { @Bean public RequestMappingHandlerMapping requestMappingHandlerMapping() { RequestMappingHandlerMapping mapping = new RequestMappingHandlerMapping(); return mapping; }}
使用@EnableAspectJAutoProxy(proxyTargetClass = true)注解开启Spring对AspectJ的支持。
maven配置:
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.9</version></dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.8.9</version></dependency>
测试类:TestAspectController.java
package com.example.mavenspringmvc.controller.test;import com.example.mavenspringmvc.aspect.AspectService;import com.example.mavenspringmvc.service.test.TestAspectService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class TestAspectController { @Autowired private TestAspectService testAspectServiceMethod; @Autowired private AspectService aspectServiceAnnotation; @RequestMapping("testAspect") public void testAspect(){ testAspectServiceMethod.printOrderInfo("DPO201711011101","2017-11-11 00:00:"); aspectServiceAnnotation.printHelloWorld(); }}
测试结果:
对Demo中用到的知识点进行说明:
切点表达式函数:
spring支持9个@AspectJ切点表达式函数,他们用不同的方式描述目标类的链接点,根据描述对象的不同,可以大致分为4中类型:
方法切点函数:通过描述目标类方法信息定义连接点;execution();
@annocation();
方法入参切点函数:通过描述目标类方法入参的信息定义链接点;args(); @args();
目标类切点函数:通过描述目标类类型信息定义连接点;within(); target(); @within(); @target();
代理类切点函数:通过描述目标类的代理类的信息定义连接点。this();
Demo中使用到execution()和@annotation()来定义切点信息:
@Before(“execution(* com.example.mavenspringmvc.service.test.TestAspectService.*(..))”)
TestAspectService类下的所有方法,第一个号代表方法可以是任何返回值,第二个号代表该类下的所有方法,(..)代表方法的参数可以是任意的;
@Pointcut(“@annotation(com.example.mavenspringmvc.annotation.Action)”)
将程序中任何使用到Action注解的方法定义为切点。
不同的增强类型:
@Before: 前置增强,在切点之前执行
@AfterReturning: 后置增强,在切点之后执行
@Around:环绕增强
@AfterThrowing: 抛出增强
@After: Final增强,不管是抛出异常还是正常退出,该增强都会执行
@DeclareParents: 环绕增强
访问连接点信息:
AspectJ使用org.aspectj.lang.JoinPoint接口表示目标类连接点对象,如果是环绕增强时,使用org.aspectj.lang.ProceedingJoinPoint表示连接点对象,该类是JoinPoint的子接口。任何一个增强方法都可以通过将第一个入参声明为JoinPoint访问到连接点上下文的信息。我们先来了解一下这两个接口的主要方法:
1)JoinPoint
java.lang.Object[] getArgs():获取连接点方法运行时的入参列表;
Signature getSignature() :获取连接点的方法签名对象;
java.lang.Object getTarget() :获取连接点所在的目标对象;
java.lang.Object getThis() :获取代理对象本身;
2)ProceedingJoinPoint
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。
- AOP、Spring的AOP
- AOP--Spring AOP
- Spring AOP 嵌套AOP
- spring AOP
- Spring AOP
- Spring AOP
- spring aop
- Spring AOP
- spring AOP
- spring aop
- Spring aop
- Spring-AOP
- Spring AOP
- spring aop
- spring aop
- Spring AOP
- Spring AOP
- Spring Aop
- Unity3D
- IO流进阶2
- Java单元测试学习
- 离散化
- 机器学习相关算法的大总结(四)
- Spring AOP
- c编辑器之clion安装,编译,控制台乱码修复
- Spreading the Wealth,UVa 11300
- AMS与Activity的交互
- 【c++】菱形继承
- 我的conky安装与配置——基于ubuntu 16.04 LTS
- 数据库视图、变量、存储过程、变量及函数
- Unity3D之UI按键绑定事件(五)
- 浅谈项目系统架构分层