Java 代理

以前我们业务代码经常需要在其中写入与业务功能不是直接相关但是很有必要大代码,如日志,事务等,这样会带来如下麻烦:

OO是一种破坏

2造成功能代码对其他类的依赖和耦合加深

3造成功能代码移植困难,可重用性降低

原则上,与这些切入性代码应该监视着功能代码,而不是功能代码通知切入性代码采取行动。

毫无疑问,这些切入性代码和功能代码应该分开才能降低耦合度,我们可使用代理完成这个要求,代理模式涉及到的三个角色:

1抽象:代理和真是对象共同接口

2代理:代理对象含有真是角色引用,与真是对象有相同接口,可以在执行真实对象前后加入切入性功能

3真实:代理角色所代表的真实对象,是我们最终要引用的对象

常见的代理有:

 1远程代理:对一个位于不同的地址空间对象提供一个局域代表对象,如RMI中的stub

2虚拟代理:根据需要将一个资源消耗很大或者比较复杂的对象,延迟加 载,在真正需要的时候才创建

3保护代理:控制对一个对象的访问权限。

4智能引用:提供比目标对象额外的服务和功能。


通过代理类这一中间层,能够有效控制对实际委托类对象的直接访问,也可以很好地隐藏和 保护实际对象,实施不同的控制策略,从而在设计上获得了更大的灵活性。

 

代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。 代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后 续处理。

先来一个接口

public interface Greeting {
 
    void sayHello(String name);
}
 
实现类

public class GreetingImpl implements Greeting {
 
    @Override
    public void sayHello(String name) {
        before();
        System.out.println("Hello! " + name);
        after();
    }
 }

静态代理


最简单的就是静态代理,单独为GreetingImpl写一个代理类

由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。

public class GreetingProxy implements Greeting {
 
    private GreetingImpl greetingImpl;
 
    public GreetingProxy(GreetingImpl greetingImpl) {
        this.greetingImpl = greetingImpl;
    }
 
    @Override
    public void sayHello(String name) {
        before();
        greetingImpl.sayHello(name);
        after();
    }
 
    private void before() {
        System.out.println("Before");
    }
 
    private void after() {
        System.out.println("After");
    }
}
 

这样GreetingProxy去代理GreetingImpl,客户端调用

public class Client {
 
    public static void main(String[] args) {
        Greeting greetingProxy = new GreetingProxy(new GreetingImpl());
        greetingProxy.sayHello("Jack");
    }
}

这样写没错,但是有个问题,XxxProxy这样的类会越来越多,如何才能将这些代理类尽可能减少呢?最好只有一个代理类。

 

动态代理

在程序运行时,运用反射机制动态创建而成

public classJDKDynamicProxy implements InvocationHandler {
 
    private Object target;
 
    public JDKDynamicProxy(Object target) {
        this.target = target;
    }
 
/**
*绑定委托对象并返回一个代理类
*/
    @SuppressWarnings("unchecked")
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(
            target.getClass().getClassLoader(),
            target.getClass().getInterfaces(),
            this
        );//this是实现invocationHandler的子类,为本身
    }
 
    @Override
    public Object invoke(Object proxy, Methodmethod, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target,args);
        after();
        return result;
    }
 
    private void before() {
        System.out.println("Before");
    }
 
    private void after() {
        System.out.println("After");
    }
}

客户端调用

public class Client {
 
    public static void main(String[] args) {
        Greeting greeting = newJDKDynamicProxy(new GreetingImpl()).getProxy();
        greeting.sayHello("Jack");
    }
}

可以看到代理类中有一个类和一个接口 

InvocationHandler接口:

public interface InvocationHandler {
  public Objectinvoke(Object proxy,Method method,Object[] args) throws Throwable;
}

参数说明:

Object proxy:指被代理的对象。

Method method:要调用的方法

Object[] args:方法调用时所需要的参数

通过实现InvocationHandler接口创建代理类调用处理器


Proxy类:

Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态地生成实现类,此类提供了如下的操作方法:

public static  ObjectnewProxyInstance(ClassLoader loader, Class<?>[] interfaces,
InvocationHandler h)
                               throwsIllegalArgumentException

参数说明:

ClassLoader loader:类加载器

Class<?>[] interfaces:得到全部的接口

InvocationHandler h:得到InvocationHandler接口的子类实例

优点:为实现接口的类代理代理对象

缺点:优点也是缺点:能代理没有接口的类


CGLIB动态代理

cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强效果 

public classCGLibDynamicProxy implements MethodInterceptor {
 
    private static CGLibDynamicProxy instance =new CGLibDynamicProxy();
 
    private CGLibDynamicProxy() {
    }
 
    public static CGLibDynamicProxygetInstance() {
        return instance;
    }
 
    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T>cls) {
        return (T) Enhancer.create(cls, this);//静态方法见说明
    }
 
    @Override
    public Object intercept(Object target,Method method, Object[] args, MethodProxy proxy) throws Throwable {
        before();
        Object result =proxy.invokeSuper(target, args);
        after();
        return result;
    }
 
    private void before() {
        System.out.println("Before");
    }
 
    private void after() {
        System.out.println("After");
    }
}
调用

public class Client {
 
    public static void main(String[] args) {
        Greeting greeting =CGLibDynamicProxy.getInstance().getProxy(GreetingImpl.class);
        greeting.sayHello("Jack");
    }
}

说明

tatic java.lang.Object

create(java.lang.Class type, Callback callback) 

          Helper method to create an intercepted object.

create

public static java.lang.Objectcreate(java.lang.Class type,
                                      Callback callback)

Helper method to create an intercepted object.For finer control over the generated instance, use a new instance of Enhancer instead of this static method.

 

Parameters:

type - class toextend or interface to implement

callback - thecallback to use for all methods

 

来自 <http://cglib.sourceforge.net/apidocs/net/sf/cglib/proxy/Enhancer.html#create(java.lang.Class,net.sf.cglib.proxy.Callback)>

总结:


通过以上的一些代理机制我们了解到,若要使系统更加复用,灵活,松耦合度,代理是少不了的,通过代理我们可以更加关注我们的业务代理,将一些切入代理进行分离,这样我们就实现了 横切对象的方法,AOP的实现就是基于代理机制的。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值