设计模式之代理模式

代理模式 Proxy Pattern

[摘自:百度百科]

组成
抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
模式结构

一个是真正的你要访问的对象(目标类),一个是代理对象,真正对象与代理。对象实现同一个接口,先访问代理类再访问真正要访问的对象。
代理模式分为静态代理、动态代理。
静态代理是由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
动态代理是在实现阶段不用关心代理类,而在运行阶段才指定哪一个对象。
静态代理

 代理对象和被代理对象实现相同的接口,但是代理对象持有被代理对象的引用。只能服务于一种类型的对象.对于稍大点的项目根本无法胜任.

// 接口
public interface Subject   
{   
  public void doSomething();   
}

// 目标类

public class RealSubject implements Subject   
{   
  public void doSomething()   
  {   
    System.out.println( "call doSomething()" );   
  }   
} 

// 代理类
public class SubjectProxy implements Subject
{
  Subject subimpl = new RealSubject();
  public void doSomething()
  {
     subimpl.doSomething();
  }
}

//测试使用
public class TestProxy 
{
   public static void main(String args[])
   {
       Subject sub = new SubjectProxy();
       sub.doSomething();
   }
}

动态代理
  • JDK动态代理

  •  在JDK1.3之后加入了可协助开发的动态代理功能.不必为特定对象与方法编写特定的代理对象,使用动态代理,可以使得一个处理者(Handler)服务于各个对象.
  •   一个处理者的类设计必须实现java.lang.reflect.InvocationHandler接口.
  •  通过InvocationHandler接口实现的动态代理只能代理接口的实现类.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class LogHandler implements InvocationHandler{
    //被代理的目标类
    private Object targetObject;
    //创建代理
    public Object createProxyInstance(Object targetObject){
        this.targetObject=targetObject;
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),targetObject.getClass().getInterfaces(),this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        //代理服务方法
        insertLog(method,args);
        //调用目标方法(原业务逻辑)
        Object ret=method.invoke(targetObject, args);
        return ret;
    }

    private void insertLog(Method method,Object[] args){
        System.out.println("logInfo:【methodName:"+method.getName()+";args:"+args+"】");
    }
实现动态代理,利用Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法获得代理类,loader就是被代理类的类加载器,interfaces 是被代理类实现的接口,它实现了几个接口,就会为其生成几个相应的代理类。此外必须要实现InvocationHandler接口,重写其invoke方法,用java.lang.reflect.Method.invoke()方法调用目标方法(可以在调用之前或者之后添加代理服务方法)。}

//测试

public class Client {
    public static void main(String[] args) {
        LogHandler logHandler=new LogHandler();
        UserManager userManager=(UserManager)logHandler.createProxyInstance(new UserManagerImpl());
        userManager.addUser(new User("杨园亮","123456"));

        OrderManager orderManager=(OrderManager)logHandler.createProxyInstance(new OrderManagerImpl());
        orderManager.addOrder(new Order("杨园亮","6666"));
    }
}

  • cglib动态代理
  • 添加jar包asm-commons-2.2.2.jar、asm-util-2.2.2.jar、asm-2.2.2.jar、cglib-nodep-2.1_3.jar。

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

public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    public Object getProxy(Class clazz) {
        // 设置需要创建子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        // 通过字节码技术动态创建子类实例
        return enhancer.create();
    }

    // 实现MethodInterceptor接口方法
    public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {
        //代理服务方法
        insertLog(method,args);
        // 通过代理类调用父类中的方法
        Object result = proxy.invokeSuper(obj, args);
        return result;
    }

    private void insertLog(Method method,Object[] args){
        System.out.println("logInfo:【methodName:"+method.getName()+";args:"+args+"】");
    }
}
    //测试

public class Client {
    public static void main(String[] args) {
        CglibProxy cglibProxy=new CglibProxy();
        UserManagerImpl userManager=(UserManagerImpl)cglibProxy.getProxy(UserManagerImpl.class);
        userManager.addUser(new User("杨园亮","666666"));
    }
}

区别

     JDK实现动态代理的代理对象和目标对象必须实现相同的接口;Cglib实现动态代理的原理则是为目标对象创建一个子类座位代理对象。如果目标类实现了接口,则必须用JDK动态代理,否则,两个都可以用。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值