代理设计模式

一、静态代理

package com.huawei.proxy;
/**
 * 静态代理。
 * 0.背景:
 *   我们不应该随意修改别人的代码,但是需要扩展功能时,可以用代理设计模式。
 *   
 * 1.包括目标对象和代理对象(好比明星)和代理对象(好比经纪人)
 * 2.方式:
 *   2.1 目标对象继承了某个类或者实现了某接口。
 *   2.2 代理对象继承了相同的父类或者实现了相同的接口。
 *   2.3 代理对象中维护了一个目标对象字段。
 *   2.4 在代理对象中复写或者实现相同的方法,从而起到扩展功能(例如事务)的效果。
 * 3.优点:
 *   3.1 不用修改目标对象代码就可以起到扩展功能的效果。
 * 4.缺点:
 *   4.1 目标对象和代理对象实现了相同的接口,代码上有重复。
 *   4.2 一旦接口发生改变,就必须要修改目标对象和代理对象代码,非常费事。
 * 
 * @author swh
 *
 */
public class TestStaticProxy 
{

    public static void main(String[] args) 
    {
        StaticTargetObj target = new StaticTargetObj();
        StaticProxyObj proxyObj = new StaticProxyObj(target);
        proxyObj.saveUser();
    }
}

interface IUserDao
{
    void saveUser();
}

class StaticTargetObj implements IUserDao
{
    @Override
    public void saveUser() {
        System.out.println("The user has been saved.");
    }
}

class StaticProxyObj implements IUserDao
{
    private StaticTargetObj target;

    public StaticProxyObj(StaticTargetObj target)
    {
        this.target = target;
    }

    @Override
    public void saveUser() 
    {
        System.out.println("开启事务");

        target.saveUser();

        System.out.println("关闭事务");
    }
}

这里写图片描述

2.JDK动态代理(接口动态代理)

package com.huawei.proxy;

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

/**
 * 
 * @author swh
 *
 * JDK动态代理:
 * 1.背景:
 *   1.1 改进静态代理的几个缺点
 * 2.思路:
 *   2.1 核心类:java.lang.reflect.Proxy.
 *             java.lang.reflect.InvocationHandler.
 * 3.优点:
 *   3.1 代理对象不用实现目标对象的接口了
 *   3.2 利用JDK API,通过反射,在内存中动态构建代理对象
 * 4.缺点:
 *   4.1 目标对象必须实现接口,否则就不能使用JDK代理
 */
public class TestJDKProxy 
{
    public static void main(String[] args) 
    {
        //创建目标对象
        JDKTargetObj target = new JDKTargetObj();
        ClassLoader classLoader = target.getClass().getClassLoader();
        Class<?>[] interfaces = target.getClass().getInterfaces();
        JDKProxyInvocationHandler handler = new JDKProxyInvocationHandler(target);

        //创建代理对象(参数:1.目标对象类加载器 2.目标对象实现的接口  3.事件处理类)
        IUserDao proxy = (IUserDao)Proxy.newProxyInstance(classLoader, interfaces, handler);

        proxy.saveUser();

    }
}
class JDKTargetObj implements IUserDao
{
    @Override
    public void saveUser() 
    {
        System.out.println("The user has been saved.");
    }
}

class JDKProxyInvocationHandler implements InvocationHandler
{
    private JDKTargetObj target;

    public JDKProxyInvocationHandler(JDKTargetObj target)
    {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
    {
        System.out.println("开启事务");

        Object invokeRet = method.invoke(target, args);

        System.out.println("关闭事务");
        return invokeRet;
    }
}

3.cglib动态代理 (子类动态代理)

package com.huawei.proxy;

import java.lang.reflect.Method;

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

/**
 * 
 * @author swh
 * 1.背景:以上两种代理都需要目标类实现接口。但是确实存在目标类未实现任何接口的情形。
 * 2.思路:
 *       核心包:cglib.jar以及asm.jar(或者spring-core.jar)
 *       核心类: Enhancer,MethodIntercepter
 * 3.优点:
 *   同1.
 * 4.缺点:
 *   4.1 目标类CglibTargetObj不能为final类型,否则报错
 *   4.2 目标类CglibTargetObj的方法如果为final/static,则不会被拦截,即只会执行目标类中的方法,     
 *       而不会执行额外的业务方法(比如开启关闭事务),不会有“增强”的效果。
 *       原因大概是final类型的类不能被子类继承,final/static的方法也不能被子类复写。
 *
 *
 *
 */
public class TestCglibProxy {

    public static void main(String[] args) {
        CglibTargetObj target = new CglibTargetObj();
        CglibTargetObj proxyInstance = (CglibTargetObj)(new CglibProxyObj(target).getProxyInstance());
        proxyInstance.saveUser();
    }

}

/**
 * 该类没有实现任何接口
 * @author swh
 *
 */
class CglibTargetObj
{
    public void saveUser()
    {
        System.out.println("the user has been saved.");
    }
}

class CglibProxyObj implements MethodInterceptor
{
    private CglibTargetObj target;

    public CglibProxyObj(CglibTargetObj target)
    {
        this.target = target;
    }

    @Override
    public Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object ret = null;
        System.out.println("开启事务");
        ret = method.invoke(this.target, objects);
        //貌似这么写也可以
        //ret = methodProxy.invoke(this.target, objects);
        System.out.println("关闭事务");

        return ret;
    }

    public Object getProxyInstance() {

        Enhancer enhancer = new Enhancer();
        //设置父类
        enhancer.setSuperclass(this.target.getClass());
        //设置回调为自身(其实MethodInterceptor就继承了CallBack接口)
        enhancer.setCallback(this);
        //创建代理对象
        return enhancer.create();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值