spring aop 面向切面编程
spring aop有注解拦截和基于方法匹配拦截两种法师。其中注解式拦截很好的控制拦截的粒度和更丰富的信息,spirng本身在事务处理@Transcational 和数据缓存@Cacheable等上都使用此形式的拦截。
pom文件中添加依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--下面三个是使用aop需要添加-->
<!--spring aop支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<!--aspectj支持-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
</dependencies>
演示注解拦截方式(基于java配置的方式进行演示)
1、在配置java中开启spring对aspectJ代理的支持。
@Configuration
@ComponentScan("com.demo.springaop")
@EnableAspectJAutoProxy // 开启spring对aspectJ代理的支持
public class AopConfig{
}
2、自定义一个注解,
@Target(ElementType.METHOD)
@Retention(RetenttionPolicy.RUNTIME)
@Documented
public @interface Action {
String name();
}
3、声明一个切面,@Aspect,使用@After、@Before、@Around定义建言(advice)。首先在切面中(加aspect注解的类)声明了一个切点,有这个自定义注解的就是切点。然后在切面中定义一个建言,可以使用上面的切点到建言的参数。例如@After("annotationPointCut()")。意思就是说,有这个aciton注解的方法,运行的时候就会先运行这个建言中的逻辑。
@Aspect // 声明一个切面
@Component // 让切面成为spirng容器管理的bean
public class MyAspect {
@Pointcut("@annotation(com.netopstec.springaop.annotation.Action)")//声明切点,有这个注解的就是切点
public void annotationPointCut(){}
@After("annotationPointCut()") //声明一个建言,使用上面声明的切点
public void after(JoinPoint joinPoint) {
MethodSignature signature = (MethodSignature)joinPont.getSignature(); // 找到切点
Method method = signature.getMethod(); // 根据那个切点获取到有aciton的方法
Action action = method.getAnnotation(Action.class); // 获取到方法上的注解中的内容,输出。
System.out.println("注解式拦截:" + action.name()); //模拟打印日志操作
}
}
4、编写被拦截的类,使用Action注解。测试这个方法的时候,结果就是建言里面的逻辑把 “注解式拦截”打印出来了。
@Service
public class DemoAnnotationService{
@Action(name="注解式拦截")
public void add() {}
}