什么是AOP(面向切面)

AOP可以说是OOP(面向对象)的补充和完善,OOP中有封装、继承、多态来建立一种对象层次结构,OOP允许你定义从上到下的关系,但却不适合定义从左到右的关系。例如日志功能。输出日志的代码往往水平地散步在所有对象层次中,但他却和核心功能毫不相关,这种散布到各处的代码被称为横切代码。

而AOP却可以通过横切技术,将那些与业务无关,却为业务模块所共同调用的逻辑进行封装起来降低模块间的耦合度。

AOP原理(代理)

AOP实际上就是由目标类的代理类实现的。就像夹汉堡一样。目标类就是其中的一块肉。其他无关操作就是面包,代理类在特定切入点添加了增强处理是面包,并回调方法是肉。

由于是代理实现AOP,而代理又分静态代理和动态代理。

下面代码,如我们需要在调用service方法前后增加try catch,有两种方法,一种是直接在代码中添加try catch,一种是使用代理。由于一个方法可能会被调用多次,却每处都要进行修改,所以我们使用代理模式进行增加功能。

public interface IService {
    public void service(String name )throws Exception;
}

public class ServiceImplA implements IService {
    @Override
    public void service(String name) throws Exception {
        System.out.println("ServiceImplA name" + name);
    }
}

1、静态代理

静态代理实现很简单,就跟上面所说的,创建一个代理类,类中面包夹肉。但是这样使得每一个接口都需要写一个代理类,所以有了动态代理。

public class ProxyServiceA implements IService {
    public IService service;
    public ProxyServiceA(IService service){
        super();
        this.service = service;
    }
    @Override
    public void service(String name) throws Exception {
        System.out.println("log start");
        try{
            service.service(name);
        }catch (Exception e){
            throw e;
        }
        System.out.println("log end");
    }
    public static void main(String []args) throws Exception {
        IService service = new ServiceImplA();
        service = new ProxyServiceA(service);
        service.service("zhjl");
    }
}

动态代理

在java中的动态代理机制中,使用了Proxy类和实现了InvocationHandler接口。实现了invoke方法来实现动态代理。

动态代理涉及到了之前反射中的描述方法,通过Proxy.newProxyInstance()生成的动态代理对象都会与实现InvocationHandler接口的对象关联。代理对象调用目标对象的方法时都会变成调用B中的invoke方法。

public class DynaProxyServiceA implements InvocationHandler {
    private Object object;
    /**
     *   将目标对象关联到InvocationHandler接口,返回代理对象obj
     *   调用代理对象的方法时,都会自动调用invoke方法
     */
    public Object bind(Object object){
        this.object = object;
        Object obj = Proxy.newProxyInstance(
                this.object.getClass().getClassLoader(),
                this.object.getClass().getInterfaces(),
                this);
        return obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result;
        System.out.println("log start");
        try{
            result = method.invoke(this.object,args);
        }catch (Exception e){
            throw e;
        }
        System.out.println("log end");
        return result;
    }
    public static void main(String [] args) throws Exception {
        IService service = (IService)new DynaProxyServiceA()
                        .bind(new ServiceImplA());
        service.service("zhjl");
    }
}

与静态代理不同,动态代理不用再为每个接口手动创建代理类,只要该对象,获取到该对象的class实例,在增强处理中来通过class中的invoke来执行方法。