• spring的AOP原理


    spring的AOP原理

      spring的aop是spring的两大特性之一。spring生态圈自带的spring shiro和log4J等横切性质的模块都系统性的一些功能,如果在业务的模块中不断写这些代码可以会出现大量的重复性代码,使用aop去做这些系统性的工作,可以大大减轻代码量。

      spring AOP实现的原理是使用的是设计模式中的代理模式。


      实现原理:

      代理模式分为两种:静态代理模式和动态代理模式

          静态代理:代理类和目标类实现同样的接口,代理类中有目标类的引用。

      接口

    public interface IHello {
        void sayHello(String str);
    }

    目标类

    public class Hello implements IHello{
        @Override
        public void sayHello(String str) {
            System.out.println("hello:" + str);
        }
    }

    代理类

    public class ProxyHello implements IHello{
        private Hello hello;
    
        public ProxyHello(Hello hello){
            this.hello = hello;
        }
    
        @Override
        public void sayHello(String str) {
            Logger.start();
            hello.sayHello(str);
            Logger.end();
        }
    
        public static void main(String[] args){
            ProxyHello hello = new ProxyHello(new Hello());
            hello.sayHello("张某某");
        }
    }

    静态代理有以下几个问题:

    1. 如果目标类没有实现接口,怎样实现代理

    2. 是不是针对不同Hello需要写很多个代理类,太麻烦了

    3. 需要实现接口中的所有方法


    查看文献可可知:

    实际工作环境中:

    使用aspectJ进行静态代理

    public class Hello {
        public void sayHello() {
            System.out.println("hello");
        }
     
        public static void main(String[] args) {
            Hello h = new Hello();
            h.sayHello();
        }
    }

    编写一个aspect

    public aspect TxAspect {
        void around():call(void Hello.sayHello()){
            System.out.println("开始事务 ...");
            proceed();
            System.out.println("事务结束 ...");
        }
    }

    编译后的代码可以更改为:

    public class Hello {
        public Hello() {
        }
     
        public void sayHello() {
            System.out.println("hello");
        }
     
        public static void main(String[] args) {
            Hello h = new Hello();
            sayHello_aroundBody1$advice(h, TxAspect.aspectOf(), (AroundClosure)null);
        }
    }
    public void ajc$around$com_listenzhangbin_aop_TxAspect$1$f54fe983(AroundClosure ajc$aroundClosure) {
            System.out.println("开始事务 ...");
            ajc$around$com_listenzhangbin_aop_TxAspect$1$f54fe983proceed(ajc$aroundClosure);
            System.out.println("事务结束 ...");
        }

    可以看出来代码在编译过程中已经被织入到代码中


    针对上面这些问题:

    java提出使用动态代理来解决这些问题

    public class DynamicProxyHello implements InvocationHandler{
        private Object target;//目标对象
    
        public Object bind(Object object) {
            this.target = object;
            return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),this.target.getClass().getInterfaces(),this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;
            Logger.start();
            result = method.invoke(this.target,args);
            Logger.end();
            return result;
        }
    
        public static void main(String[] args){
            IHello hello= (IHello) new DynamicProxyHello().bind(new Hello());
            hello.sayHello("张某某");
        }
    }

    可以看出可以生成任一接口的代理类,并且针对任一方法织入增强方法,但是缺点是仍然目标类需要实现接口


    第三中方式:

    使用cglib来进行处理

    cglib生成目标类的子类,然后将需要增强的方法重写,cglib也有局限,对于无法生成子类的类(final类)也无法处理

  • 相关阅读:
    sp_addlinkedserver的一些操作
    MVC3.0,路由设置实现伪静态IIS中404错误
    Chrome本地跨域请求设置,实现HTML模板页
    jQuery异步请求(如getJSON)跨域解决方案
    【海淘域名】GoDaddy账户被锁定后的解决方法
    jquery-qrcode客户端二维码生成类库扩展--融入自定义Logo图片
    JavaScript获取URL参数方法总汇
    ASP.NET 内联代码、内联表达式、数据绑定表达式使用方法罗列(形式就是常说的尖括号 百分号 等于号 井号)
    如何获取Repeater行号(索引)、记录总数?
    判断jquery类库是否加载,如未加载则加载。
  • 原文地址:https://www.cnblogs.com/zhangchiblog/p/8982936.html
Copyright © 2020-2023  润新知