zoukankan      html  css  js  c++  java
  • 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类)也无法处理

  • 相关阅读:
    Dynamics AX 2012 R2 配置E-Mail模板
    Dynamics AX 2012 R2 设置E-Mail
    Dynamics AX 2012 R2 为运行失败的批处理任务设置预警
    Dynamics AX 2012 R2 耗尽用户
    Dynamics AX 2012 R2 创建一个专用的批处理服务器
    Dynamics AX 2012 R2 创建一个带有负载均衡的服务器集群
    Dynamics AX 2012 R2 安装额外的AOS
    Dynamics AX 2012 R2 将系统用户账号连接到工作人员记录
    Dynamics AX 2012 R2 从代码中调用SSRS Report
    Dynamics AX 2012 R2 IIS WebSite Unauthorized 401
  • 原文地址:https://www.cnblogs.com/zhangchiblog/p/8982936.html
Copyright © 2011-2022 走看看