Spring aop之代理模式

最近学习spring aop时发现其大量使用了代理模式,于是就想着研究一下代理模式的实现原理。

代理模式

实现原理图
代理模式是常用的java设计模式,如上图所示,代理类和实现类实现了同一个接口,而代理类中则具有现有对象,通过代理类去操作现有对象,那么我们就可以在代理类中增加很多操作,包括前置增强、后置增强、环绕增强、异常增强等,这也就能解决我们实际当中遇到的一些问题,例如延迟对象的创建、控制对象的访问等。

静态代理

静态代理是由程序员创建或特定工具自动生成源代码,再对其编译。最大的特点就是在程序运行时代理类的.class文件就已经存在了,但是这有一个很大的缺陷即每一个代理类只能为一个接口服务。静态代理的实现如下
首先定义一个接口

//产品接口
public interface ProductBiz {
    public void addProduct();
}

接着定义一个接口实现类

//产品实现类
public class ProductImpl implements ProductBiz {

    @Override
    public void addProduct() {
        System.out.println("增加产品");

    }

}

再定义一个接口代理类:

//产品实现代理类
public class ProductImplProxy implements ProductBiz {
    //在代理类中必须 有一个真实对象的引用
    private ProductBiz productBiz;
    public ProductImplProxy(ProductBiz productBiz){
        this.productBiz=productBiz;
    }
    @Override
    public void addProduct() {
        before();
        productBiz.addProduct();
        after();

    }
    private void before(){
        System.out.println("********************");
        System.out.println("前置增强");
        System.out.println("*********************");

    }
    private void after(){
        System.out.println("********************");
        System.out.println("后置增强");
        System.out.println("*********************");    
    }


}

测试类

public class Test {

    public static void main(String[] args) {
        ProductBiz pb=new ProductImplProxy(new ProductImpl());
        pb.addProduct();

    }

}

测试结果

测试结果

动态代理

动态代理在程序运行时,利用反射机制动态创建,有jdk动态代理和cglib动态代理两种:

jdk动态代理

jdk动态代理是依靠接口实现的,没有实现接口的类是不能使用jdk动态代理的。

JDK动态代理中包含一个类和一个接口:
InvocationHandler接口:

public interface InvocationHandler { 
/*Object proxy:指被代理的对象 
Method method:要调用的方法 
Object[] args:方法调用时所需要的参数
*/
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable; 
} 

首先定义接口

//产品接口
public interface ProductBiz {
    public void addProduct();
}
//产品实现类
public class ProductBizImpl implements ProductBiz {

    @Override
    public void addProduct() {
        System.out.println("增加产品");

    }

}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//产品实现代理类
public class ProductImplProxy implements InvocationHandler {
    // 在代理类中必须 有一个真实对象的引用
    private Object targetObject;

    public Object newInstance(Object targetObject) {
        this.targetObject = targetObject;
        /*
         * ClassLoader loader:类加载器 Class<?>[] interfaces:得到全部的接口
         * InvocationHandler h:得到InvocationHandler接口的子类实例
         */
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                targetObject.getClass().getInterfaces(), this);

    }

    private void before() {
        System.out.println("********************");
        System.out.println("前置增强");
        System.out.println("*********************");

    }

    private void after() {
        System.out.println("********************");
        System.out.println("后置增强");
        System.out.println("*********************");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        before();
        Object returnValue = method.invoke(targetObject, args);
        after();
        return returnValue;
    }

}
public class Test {

    public static void main(String[] args) {
        ProductImplProxy pip=new ProductImplProxy();
        ProductBiz pbproxy=(ProductBiz) pip.newInstance(new ProductBizImpl());
        pbproxy.addProduct();


    }

}

测试结果
这里写图片描述

cglib动态代理

cglib弥补了jdk代理的不足,是针对类来实现代理的,即使没有实现接口的类,也能生成代理,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
cglib包下载地址:http://pan.baidu.com/s/1mglEbZM 密码:0rno

//产品接口
public interface ProductBiz {
    public void addProduct();
}
//产品实现类,其实并没有实现接口
public class ProductBizImpl {

    public void addProduct() {
        System.out.println("增加产品");

    }

}
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

//产品实现代理类
//方法拦截器
public class ProductImplProxy implements MethodInterceptor {
    // 在代理类中必须 有一个真实对象的引用
    private Object targetObject;

    public Object newInstance(Object targetObject) {
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.targetObject.getClass());
        // 回调方法
        enhancer.setCallback(this);
        // 创建代理对象
        return enhancer.create();

    }

    private void before() {
        System.out.println("********************");
        System.out.println("前置增强");
        System.out.println("*********************");

    }

    private void after() {
        System.out.println("********************");
        System.out.println("后置增强");
        System.out.println("*********************");
    }

    @Override
    public Object intercept(Object obj, Method arg1, Object[] args,
            MethodProxy proxy) throws Throwable {
        before();
        Object returnValue = proxy.invokeSuper(obj, args);
        after();
        return returnValue;
    }

}
public class Test {

    public static void main(String[] args) {
        ProductImplProxy pip=new ProductImplProxy();
    ProductBizImpl pbi= (ProductBizImpl) pip.newInstance(new ProductBizImpl());
    pbi.addProduct();


    }

}

测试结果

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值