SpringAOP
主要注解:
- @Aspect
- @Pointcut
- Advice
Point express:切面表达式
designators : 指示器:描述通过什么样的方式匹配想要的类的什么方法
匹配方法:使用通配符把执行的方法拦截下来
execution()
//匹配任何以find开头而且只有一个Long参数的方法 @Pointcut("execution(* *..find*(Long))") public void argsDemo1(){}
//匹配任何以find开头而且第一个参数为Long的方法 @Pointcut("execution(* *..find*(Long,..))") public void argsDemo3(){}
匹配注解:标注service类下面的所有的方法,在方法上面有指定注解的方法,方法里面有一个参数,是某一个类,而该类有指定注解,可以筛选
@target():
//匹配标注右Repository的类地下的方法,要求annotation的RetentionPolicy级别为RUNTIME @Pointcut("@target(org.springframework.stereotye.Repository)") public void annoTargetDemo(){}
@args():
//匹配传入的参数类标注右Repository注解的方法 @Pointcut("@args(org.springframework.stereotype.Repository)") public void annoArgsDemo(){}
@within():
//匹配标注右Beta的类底下的方法,要求的annotation的RetentionPolicy级别为CLASS @Pointcut("@within(com.google.common.annotations.Beta)") public void annoWithinDemo(){}
@annotation():
//匹配方法标注右AdminOnly的注解的方法 @Pointcut("@annotation(com.debuggg.demo.security.AdminOnly)") public void annoDemo(){}
匹配包/类型:匹配指定的包,类型及其子类
within()
//匹配ProductService类里面的所有方法 @Pointcout("within(com.debuggg.service.ProductService)") public void matchType(){}
//匹配com.debuggg包及其子包下所有类的方法 @Pointcut("within(com.debuggg..*)")
匹配对象:匹配指定对象,匹配spring托管的指定对象
this()
//匹配AOP对象的目标对象为指定类型的方法,即DemoDao的aop代理对象的方法,其实就是实现该类的所有的方法 //即目标对象的代理对象 @Pointcut("this(com.debuggg.DemoDao)") public void thisDemo(){}
bean()
//匹配所有以Service结尾的bean里面的方法 @Pointcut("bean(*Service)") public void beanDemo(){}
target()
//匹配实现IDao接口的目标对象(而不是aop代理后的对象)的方法,这里即DemoDao的方法,其实就是实现该类的所有的方法 @Pointcut("target(com.debuggg.IDao)") public void targetDemo(){}
匹配参数:匹配方法的第一个参数是String类型的(例子)
args()
//匹配第一个参数为Long型的方法 @Pointcut("args(Long,..)") public void argsDemo4(){}
//匹配任何只有一个Long参数的方法 @Pointcut("args(Long)") public void argsDemo2(){} //匹配任何只有一个Long参数的方法而且是在某个子包下面 @Pointcut("args(Long) && within(com.debuggg.service.*)") public void matchArgs(){}
wildcards 通配符
- *:匹配任意数量的字符
- ..:一般用于匹配任意数的子包或参数
- +:匹配指定类及其子类
operators 操作符(逻辑)
- &&:与
- || :或
- !:非
execution()表达式
格式:其中标注问号的表示可以省略
execution(
modifier-pattern?:修饰符
ret-type-pattern:返回值
declaring-type-pattern:描述包名
name-pattern(param-pattern):方法名(方法参数)
throws-pattern? :匹配方法抛出的异常
)
例如:
//匹配public类型任意返回值,拦截了com.debuggg.service包下以Service结尾的类的任意方法,以及任意参数
@Pointcut("execution(public * com.debuggg.service.*Service.*(..))" )
//匹配public类型任意返回值,拦截了com.debuggg.service包以及子包下以Service结尾的类的任意方法,以及任意参数
@Pointcut("execution(public * com.debuggg.service..*Service.*(..))" )
//匹配public类型任意返回值,拦截了com.debuggg.service包以及子包下以Service结尾的类的任意方法,以及任意参数,以及抛出了IllegalAccessException异常的方法
@Pointcut("execution(public * com.debuggg.service..*Service.*(..)) throws java.lang.IllegalAccessException" )
public void matchType(){}
@Before("matchType()")
public void test(){}
5种Advice注解
- @Before,前置通知
- @After(finally),后置通知,方法执行完之后
- @AfterReturning,返回通知,成功执行之后
- @AfterThrowing,异常通知,抛出异常之后
- @Around,环绕通知
@Before:方法执行之前
@Pointcut("@annotation(com.debuggg.apspecttest.AopAnnotationTest)")
public void matchType(){}
@Before("matchType()")
public void before(){
System.out.println();
System.out.println("###before");
}
After:方法执行之后
@After("matchType() && within(com.debuggg..*)")
public void afterDemo(){
System.out.println("#################after aop by within");
}
@AfterReturning("matchType() && within(com.debuggg..*)")
public void afterReturning(){
System.out.println("#################after aop by within");
}
@AfterThrowing("matchType() && within(com.debuggg..*)")
public void afterThrowing(){
System.out.println("#################after aop by within");
}
@Around
@Around("matchType() && within(com.debuggg..*)")
public Object AfterThrowing(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("#############before");
try{
Object result = pjp.proceed(pjp.getArgs());
System.out.println("###################return");
return result;
}catch (Throwable e){
System.out.println("#################ex");
throw e;
}finally {
System.out.println("##################after");
}
}
Advice中的参数及结果绑定
@Before(value = "matchType() && within(com.debuggg..*) && args(userId)")
public void before(JoinPoint joinPoint,Long userId){
System.out.println("before ,args:" + userId);
}
@AfterReturning(value = "matchType() && within(com.debuggg..*)",returning = "returnValue")
public void afterReturning(Object returnValue){
if(returnValue != null){
System.out.println("after return , result:" + returnValue)
}
}
AOP原理
动态代理:
JDK方式
参考:http://debuggg.com/article/209
cglib实现方式
被代理类的接口:
public interface Subject {
void hello();
}
被代理类
public class RealSubject implements Subject {
@Override
public void hello() {
System.out.println("hello");
}
}
动态代理cglib类:
public class DemoMethodInterceptor implements MethodInterceptor {
public Object getInstance(Object o){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(o.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before in cglib");
Object result = null;
try {
result = methodProxy.invokeSuper(o, objects);
System.out.println("after return");
}catch (Exception e){
System.out.println("ex: " + e.getMessage());
throw e;
}finally {
System.out.println("after in cglib");
}
return result;
}
}
测试类:
public class Client {
public static void main(String[] args) {
// Enhancer enhancer = new Enhancer();
// enhancer.setSuperclass(RealSubject.class);
// enhancer.setCallback(new DemoMethodInterceptor());
// Subject subject = (Subject) enhancer.create();
Subject subject = (Subject) new DemoMethodInterceptor().getInstance(new RealSubject());
subject.hello();
}
}