美文网首页一位攻城狮的自我修养
Spring AOP框架学习文档!分析说明接口引入类Introd

Spring AOP框架学习文档!分析说明接口引入类Introd

作者: 攻城狮Chova | 来源:发表于2022-01-05 22:33 被阅读0次
    Spring AOP文档

    introduction和advice比较

    • introduction: 用于给目标引入新的接口,比如锁,状态功能时.生成一个mix-in的接口
    • advice: 只是在原有接口的基础上增加附加内容

    introduction

    通过IntroductionInterceptor接口实现

    • 实现一个introduction需要三个内容:
      • 将要添加的新接口的定义
      • 该新接口的实现,在实现的class中,必须实现Spring的IntroductionInterceptor接口
      • IntroductionAdvisor接口的实现
    public interface IntroductionInterceptor extends MethodInterceptor {
    
      /*
           * 此方法用于判断该introduction实现是否实现了intf接口类
           * 所有对inf接口的调用方法都会转发给incoke方法,由invoke方法完成相应的任务
           *
       * @param intf 接口类
       * @return boolean 该introduction实现是否实现的接口类
           */
      boolean implementsInterface(Class intf);
    
      // invoke()方法来源于MethodInterceptor
      invoke(MethodInvocation invocation);
    }
    
    • 示例: 添加一个aduitable功能

    1.添加新的接口定义:

    /**
     * 1. auditable接口定义
     */
     public interface Auditable {
        void setLastModifiedDate(Date date);
        Date getLastModifiedDate();
     }
    

    2.该新的接口的实现,必须实现Spring的IntroductionIntercepter:

    /**
     * 2. auditable接口的实现,同时要实现IntroductionIntercepter接口
     */
    public class AuditableMixin implements IntroductionInterceptor, Aduitable {
    
        /*
         * 实现IntroductionInterceptor接口中的implementsInterface接口
         */
         public boolean implementsInterface(Class intf) {
            // AuditableMixin实现了Auditable类的功能
            return intf.isAssignableFrom(Auditable.class);
         }
    
        public Object invoke(MethodInvocation m) throws Throwable {
            /*
             * 对invoke中的参数m进行判断,当前的调用是否在implementsInterface范围内
             * 即当前的调用是否是auditable接口中的方法
             */
            if (implementsInterface(m.getMethod().getDeclaringClass())) {
                /*
                 * 调用引入的方法,来源于auditable接口,这样就可以给target添加新的auditable接口
                 * this就是对象本身
                 */ 
                 return m.getMethod().invoke(this, m.getArguments());
            } else {
                // 调用其余方法
                return m.proceed()
            }
        }
        // 实现auditable接口
        private Date lastModifiedDate;
    
        public Date getLastModifiedDate() {
            return lastModifiedDate;
        }
        public void setLastModifiedDate(Date lastModifiedDate) {
            this.latsModifiedDate = lastModifiedDate;
        }
    }
    

    通过DelegatingIntroductionInterceptor接口实现

    • introduction除了直接实现IntroductionInterceptor接口外,还可以通过继承DelegatingIntroductionInterceptor类实现
    • DelegatingIntroductionInterceptor默认实现了IntroductionInterceptor接口中的implementsInterfaceinvoke两个方法,仅仅需要自定义实现auditable接口
    • 示例: 通过DelegatingIntroductionInterceptor实现AuditableMixin
    public class AuditableMixin extends DelegatingIntroductionInterceptor implements Auditable {
        private Date lastModifiedDate;
        
        public Date getLastModifiedDate() {
            return lastModifiedDate;
        }
        public void setLastModifiedDate(Date lastModifiedDate) {
            this.lastModifiedDate = lastModifiedDate;
        }
    }
    

    Introduction总结

    • 上述AuditableMixin的实现都是给Target添加行为,未改变Target的原有行为.因为在invoke方法的实现中,还是会转发给Target
    • 如果需要修改Target的行为:
      • 比如给Target增加lock接口,一旦处于locked状态,再次调用Target方法就会出现异常
      • 需要修改invoke方法
    public class ImmutableMixin extends DelegatingIntroductionInterceptor implements Immutable {
        private boolean immutable;
    
        public void setImmutable(boolean immutable) {
            this.immutable = immutable;
        }
    
        /**
         * 修改invoke方法
         */
         public Object invoke(MethodInvocation m) throws Throwable {
            String name = mi.getMethod().getName();
    
           /*
            * 如果已经是immutable,就不可以调用setXxx()方法
            * 这样就改变了Target的行为,而不仅仅是添加行为
            */
            if (immutable && name.indexOf("set") == 0) {
                throw new IllegalModificationException();
            }
             return super.invoke(mi);
         }
    }
    

    Spring中Introduction

    • Spring中的Introduction需要有Advisor: IntroductionAdvisor
    • Spring中使用Introduction的注意点:
      • Spring中使用的是动态AOP, 并没有像AspectJ使用静态的代码编译的方式生成AOP代码
      • 因此只有从SpringBeanFactory中得到的Introduction Bean才会被introduced
      • 直接在代码中new出来的target对象则不具有Introduction功能
      • 可以使用一个Factory来封装对Introduction的创建

    相关文章

      网友评论

        本文标题:Spring AOP框架学习文档!分析说明接口引入类Introd

        本文链接:https://www.haomeiwen.com/subject/rmakcrtx.html