SpringAOP浅析
1、问题
问题:想要添加日志记录、性能监控、安全监测
2、最初解决方案
2.1、最初解决方案
2.2、抽象类进行共性设计,子类进行个性设计,此处不讲解,缺点一荣俱荣,一损俱损
2.3、使用装饰器模式/代理模式改进的解决方案
- public class MyInvocationHandler implements InvocationHandler {
- private Object target;
- public MyInvocationHandler(Object target) {
- this.target = target;
- }
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- //1.记录日志 2.时间统计开始 3.安全检查
- Object retVal = method.invoke(target, args);
- //4.时间统计结束
- return retVal;
- }
- public static Object proxy(Object target) {
- return Proxy.newProxyInstance(target.getClass().getClassLoader(),
- target.getClass().getInterfaces(), new MyInvocationHandler(target));
- }
- }
public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler(Object target) { this.target = target; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //1.记录日志 2.时间统计开始 3.安全检查 Object retVal = method.invoke(target, args); //4.时间统计结束 return retVal; } public static Object proxy(Object target) { return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new MyInvocationHandler(target)); } }
编程模型
- //proxy 在其上调用方法的代理实例
- //method 拦截的方法
- //args 拦截的参数
- Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Object retVal=null;
- //预处理
- //前置条件判断
- boolean ok = true;
- if(!ok) {//不满足条件
- throw new RuntimeException("你没有权限");
- }
- else {//反射调用目标对象的某个方法
- retVal = method.invoke(target, args);
- }
- //后处理
- return retVal;
- }
//proxy 在其上调用方法的代理实例 //method 拦截的方法 //args 拦截的参数 Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object retVal=null; //预处理 //前置条件判断 boolean ok = true; if(!ok) {//不满足条件 throw new RuntimeException("你没有权限"); } else {//反射调用目标对象的某个方法 retVal = method.invoke(target, args); } //后处理 return retVal; }
缺点:使用麻烦,不能代理类,只能代理接口
- public class MyInterceptor implements MethodInterceptor {
- private Object target;
- public MyInterceptor(Object target) {
- this.target = target;
- }
- @Override
- public Object intercept(Object proxy, Method method, Object[] args,
- MethodProxy invocation) throws Throwable {
- //1.记录日志 2.时间统计开始 3.安全检查
- Object retVal = invocation.invoke(target, args);
- //4.时间统计结束
- return retVal;
- }
- public static Object proxy(Object target) {
- return Enhancer.create(target.getClass(), new MyInterceptor(target));
- }
- }
public class MyInterceptor implements MethodInterceptor { private Object target; public MyInterceptor(Object target) { this.target = target; } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy invocation) throws Throwable { //1.记录日志 2.时间统计开始 3.安全检查 Object retVal = invocation.invoke(target, args); //4.时间统计结束 return retVal; } public static Object proxy(Object target) { return Enhancer.create(target.getClass(), new MyInterceptor(target)); } }
编程模型
- //proxy 在其上调用方法的代理实例 method拦截的方法 args 拦截的参数
- //invocation 用来去调用被代理对象方法的
- @Override
- public Object intercept(Object proxy, Method method, Object[] args,
- MethodProxy invocation) throws Throwable {
- //预处理
- //前置条件判断
- boolean ok = true;
- if(!ok) {//不满足条件
- throw new RuntimeException("出错了");
- }
- else {//调用目标对象的某个方法
- Object retVal = invocation.invoke(target, args);
- }
- //后处理
- return retVal;
- }
//proxy 在其上调用方法的代理实例 method拦截的方法 args 拦截的参数 //invocation 用来去调用被代理对象方法的 @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy invocation) throws Throwable { //预处理 //前置条件判断 boolean ok = true; if(!ok) {//不满足条件 throw new RuntimeException("出错了"); } else {//调用目标对象的某个方法 Object retVal = invocation.invoke(target, args); } //后处理 return retVal; }
动态代理本质
- @Aspect
- public class PayEbiAspect {
- @Pointcut(value="execution(* pay(..))")
- public void pointcut() {}
- @Around(value="pointcut()")
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- //1.记录日志
- //2.时间统计开始
- //3.安全检查
- Object retVal = pjp.proceed();//调用目标对象的真正方法
- //4.时间统计结束
- return retVal;
- }
- }
@Aspect public class PayEbiAspect { @Pointcut(value="execution(* pay(..))") public void pointcut() {} @Around(value="pointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable { //1.记录日志 //2.时间统计开始 //3.安全检查 Object retVal = pjp.proceed();//调用目标对象的真正方法 //4.时间统计结束 return retVal; } }
- //2 切入点
- @Pointcut(value="execution(* *(..))")
- public void pointcut() {}
- //3 拦截器的interceptor
- @Around(value="pointcut()")
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- Object retVal=null;
- //预处理
- //前置条件判断
- boolean ok = true;
- if(!ok) {//不满足条件
- throw new RuntimeException("你没有权限");
- }
- else {//调用目标对象的某个方法
- retVal = pjp.proceed();
- }
- //后处理
- return retVal;
- }
//2 切入点 @Pointcut(value="execution(* *(..))") public void pointcut() {} //3 拦截器的interceptor @Around(value="pointcut()") public Object around(ProceedingJoinPoint pjp) throws Throwable { Object retVal=null; //预处理 //前置条件判断 boolean ok = true; if(!ok) {//不满足条件 throw new RuntimeException("你没有权限"); } else {//调用目标对象的某个方法 retVal = pjp.proceed(); } //后处理 return retVal; }
·代码纠结/混乱——当一个模块或代码段同时管理多个关注点时发生这种情况。如我既要实现业务、还要实现安全和事务。即有些关注点同时被多个不同的模块实现。实现了重复的功能。
·代码分散——当一个关注点分布在许多模块中并且未能很好地局部化和模块化时发生这种情况 。如许多模块调用用户是否登录验证代码。调用了重复的功能。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。