AOP
Aspect Oriented Programming
动态代理
//为目标对象创建代理对象
//方法执行器,帮我们目标对象执行目标方法
InvocationHandler h = new InvocationHandler(){
/**
*Object proxy :代理对象,给jdk使用,不要动
*Method method:当前将要执行的目标对象方法
*Object[] args: 这个方法调用时外界传入的参数
*/
Publie Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
Object result = method.invoke(calculator, args);
//返回值必须返回出去
return result;
}
}
Class<?>[] interfaces = calculator.getClasss().getInterfaces();
ClassLoader loader = calculator.getClass().getClassLoader();
Proxy.newProxyInstance(loader, interfaces,h);
代理对象和被代理对象唯一的关联:实现同一个接口
动态代理的缺点
1)复杂
2)jdk默认的动态代理,如果目标对象没有实现任何接口,无法创建代理对象
基本概念:
切面类
横切关注点
通知方法
连接点
切入点
切入点表达式
配置步骤
1)将目标类和切面类加入到容器
2) 告诉spring哪个是切面类@Aspect
3)告诉spring切面类每个方法何时运行
4)开启基于注解的aop功能 aop名称空间
aop:aspectj-autoproxy</aop:aspectj-autoproxy>
通知注解
@Before 前置通知 目标方法之前
@After 后置通知目标方法结束之后
@AfterReturning 返回通知 目标方法正常返回之后
@AfterThrowing 异常通知目标方法抛出异常之后
@Around 环绕通知
匹配任意类型参数
@AfterReturning(value=“execution(public int com.impl.MyMath*(int,*))”,returning=“result”)
匹配任意个参数
@Before(“execution(int com.impl.MyMath*(…))”)
匹配任意多层路径
@AfterThrowing(value=“execution(int com.impl…MyMath*(…))”,throwing=“exception”)
获取bean
有接口,ioc.getBean(“接口类型”)
没有接口,ioc.getBean(“本类型”)
通知方法执行顺序
正常:@Before----@After-----@AfterReturning
异常:@Before——@After——@AfterThrowing
在通知方法运行时,拿到目标方法的信息
JointPoint jointPoint
jointPoint.getArgs()
jointPoint.getSignature()
Spring对通知方法的约束不严格,唯一要求是参数不能乱写,每个参数必须是Spring认识的
表达式重用
@PointCut(“execution(* *(…))”)
Public void myPointCut(){};
环绕通知
@Around
public Object myAround(ProceedingJointPoint pjp){
Object[] args = pjp.getArgs();
Object proceed = null;
try{
proceed = pjp.proceed(args);
}catch(Exception e){
} finally{
}
}
顺序:环绕前置—普通前置—目标方法执行—环绕正常返回/异常—环绕后置—普通后置—普通正常返回/异常
@Order(1) //改变切面顺序
基于xml配置
aop:config
//全局切入点表达式
<aop:pointcut expression=“execution(* (…)” id=“globalPointCut”>
<aop:aspect ref=“LogUtils”>
//内部切入点表达式
<aop:pointcut expression=“execution( *(…)” id=“myPointCut”>
<aop:before method=“LogStart” pointcut=“myPointCut”/>
<aop:after-returning method=“LogReturn” pointcut=“myPointCut” returning=“result”/>
<aop:after-throwing method=“LogException” pointcut=“myPointCut” throwing=“exception”/>
</aop:aspect>
</aop:config>