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类)也无法处理

 

posted on 2018-05-02 22:38  张小泽的小号  阅读(301)  评论(0编辑  收藏  举报

导航