一 概述
SpringAOP的实现主要有两种代理方式:
1.基于JDK的动态代理:是面向接口,实现具体的接口,形成代理对象,同时运用到反射机制。
2.基于CGLIB的动态代理:以继承的方式动态生成目标类的代理,基于ASM字节码库实现。
二 SpringAOP的具体实现方式
1. 通过XML配置方式实现
2. 通过注解的方式实现(目前主要的方式)
三 SpringAOP的主要注解
1. @Aspect:用来标注某个类为切面配置类
@Aspect
@Component
public class SecurityAspect {
@Autowired
AuthService authService;
@Pointcut("@annotation(AdminOnly)")
public void adminOnly() {
}
@Before("adminOnly()")
public void checkAccess(){
authService.checkAccess();
}
}
2. @Pointcut:可以理解为切入点,指定我们要织入代码的具体位置。
四 SpringAOP中的Pointcut expression(切面表达式)
切面表达式主要由三部分组成:
1. 指示器(designators):指定方式匹配目标Java方法的实例。
- 匹配方法:execution()通过通配符执行流将想要拦截的方法直接筛选出来(重点)。
- modifier-pattern?(修饰符pattern,可省略)
- ret-type-pattern (返回值pattern)
- declaring-type-pattern? (包名pattern,可省略)
- name-pattern(param-pattern) (方法名,方法参数pattern)
- throws-pattren? (匹配方法异常的pattern,可省略)
- 匹配注解:@target(),@args(),@within(),@annotation()可以筛选出有指定注解的方法。
//匹配方法标注有AdminOnly的注解的方法
@Pointcut("@annotation(com.zero.springaop.annotation.AdminOnly)")
public void adminOnly() {
}
//匹配方法标注有NeedSecureed注解的类中方法,要求annotation的RetentionPolicy级别为ClASS
@Pointcut("@within(com.zero.springaop.annotation.NeedSecured)")
public void secured(){
}
//匹配标注有Repository注解的类中方法,要求annotation的RetentionPolicy级别为RUNTIME
@Pointcut("@target(org.springframework.stereotype.Repository)")
public void target(){
}
//匹配传入的参数类标注有Repositroy注解的方法
@Pointcut("@args(org.springframework.stereotype.Repository)")
public void args(){
}
//注意@within和@target注解在Spring环境中是一样的,而不在Spring环境中前者注解的RetentionPolicy为CLASS,后者的RetentionPolicy则是RUNTIME
- 匹配包/类型:within()。
//匹配ProductService类中的所有方法
@Pointcut("within(com.zero.springaop.service.ProductService)")
public void mathType(){
};
//匹配com.zero包及其子包中所有类的方法
@Pointcut("within(com.zero..*)")
public void mathPackage(){
}
- 匹配对象:this(),bean(),target()。
//匹配AOP对象的目标对象为指定类型的方法,及UserServiceImpl的aop代理对象的方法
@Pointcut("this(com.zero.springaop.service.impl.UserServiceImpl)")
public void thisInstance(){
}
//匹配实现UserService接口的目标对象(而不是AOP代理后的对象)的方法,这里即UserServiceImpl的方法
@Pointcut("target(com.zero.springaop.service.UserService)")
public void targetInstance(){
}
//匹配所有以Service结尾的bean中的方法
@Pointcut("bean(*Service)")
public void beanInstance(){
}
//对于this和target的区别是this可以拦截动态生成的方法,而target则拦截不了
- 匹配参数:args()。
//匹配任何以get开头且只有一个类型为Long参数的方法
@Pointcut("execution(* *..get*(Long))")
public void argsInstance(){
}
//匹配任何另有一个Long参数的方法
@Pointcut("args(Long)")
public void argsInstanceL(){
}
//匹配任何以get开头的而且第一个参数为Long型的方法
@Pointcut("execution(* *..get*(Long,..))")
public void argsInstances() {
}
//匹配第一个参数为Long型的方法
@Pointcut("args(Long,..)")
public void argsInstanced(){
}
2. 通配符 (wildcards):对于比较多了匹配实例,为了避免一一列举,我们可以使用通配符来完成。
- * 用于匹配任意数量的字符
- + 用于匹配指定类及其子类(类似于java泛型中的extends,同时匹配基类与所有集成基类的子类)
- .. 一般用于匹配任意数量的子包或参数
3. 运算符(operators):进行逻辑上的或与非运算。如:||(或),&&(与),!(非)。
扫描二维码关注公众号,回复:
12552986 查看本文章