谈谈java代理模式的认识二

让我们就接着上篇博客的静态代理来开始今天的动态代理。

一、动态代理

静态代理需要在运行之前就写好代理类,这样就造成了代码的大量重复,所以我们通过动态代理在运行时期动态生成业务类的代理类,那么动态代理类是如何实现的呢?

动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。 原来是利用反射的机制来实现的,今天我们不讨论反射,我们看JDK的动态代理的实现。

JDK动态代理中包含一个类和一个接口: InvocationHandler接口,和我们定义的一个实现类“Proxy“,这是一个万能的代理类,我们就是通过这个代理类来动态代理的。

      InvocationHandler接口: 

public interface InvocationHandler {

public Object invoke(Object proxy,Method method,Object[] args) throws Throwable;

}

参数说明:

Object proxy:指被代理的对象。

Method method:要调用的方法

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

可以将InvocationHandler接口的子类想象成一个代理的最终操作类,替换掉ProxySubject。

      Proxy类:

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

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

throws IllegalArgumentException

参数说明:

ClassLoader loader:类加载器

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

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

     Ps:类加载器 

在Proxy类中的newProxyInstance()方法中需要一个ClassLoader类的实例,ClassLoader实际上对应的是类加载器,在Java中主要有一下三种类加载器;

Booststrap ClassLoader:此加载器采用C++编写,一般开发中是看不到的;

Extendsion ClassLoader:用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类;

AppClassLoader:(默认)加载classpath指定的类,是最常使用的是一种加载器。

二、使用JDK的动态代理

还是使用上篇博客的代码,我们也是简单的说三步来实现:业务接口,业务实现类的创建;代理类的创建,业务的调用。

我们看代码实现:

<span style="font-family:KaiTi_GB2312;font-size:18px;"> /**
     * 定义一个业务接口
     * @author Cassie
     */
    public interface Account {
        // 查询
        public void queryAccount ();    

        // 修改
        public void updateAccount ();
    }    

    /**
     * 接口实现类(包含业务逻辑)
     *  即:委托类
     * @author Cassie
     */
    public class AccountImpl implements Account{    

        @Override
        public void queryAccount() {
            System.out.println("查询方法...");
        }    

        @Override
        public void updateAccount() {
            System.out.println("修改方法...");
        }    

    }</span>

关键的动态代理是如下几行代码:该处的代理类Proxy 不去实现具体的某个业务接口,而是实现了JDK提供的InvocationHander类。在Proxy中我们不需要知道具体的业务类,即委托类,在运行之前,讲委托类和代理类进行解耦,在运行期才发生的联系,是通过这句话实现的:private object target。然后在调用的时候通过getInstance 在确定谁是委托对象。

<span style="font-family:KaiTi_GB2312;font-size:18px;">/**
 * JDK动态代理代理类
 *
 * @author Cassie
 *
 */
public class Proxy implements InvocationHandler {
    private Object target;
    /**
     * 绑定委托对象并返回一个代理类
     * @param target
     * @return
     */
    public Object GetInstance(Object target) {
        this.target = target;
        //取得代理对象
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }  

    @Override
    /**
     * 调用方法
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        Object result=null;
        System.out.println("before");
        //执行方法
        result=method.invoke(target, args);
        System.out.println("after");
        return result;
    }  

} </span>

再看我们的客户端调用:这时候才传入真正的委托类。

<span style="font-family:KaiTi_GB2312;font-size:18px;">public class TestProxy {  

    public static void main(String[] args) {
        Proxy proxy = new Proxy();
	// 在这里进行真正的对象传入
        Account account= (Account )proxy.getInstance(new AccountImpl());
        proxy.queryAccount();
    }  

}</span>

以上过程就是JDK动态代理的实现,我们发现JDK动态代理帮我们讲代理类和委托类的绑定关系延迟了,什么时候用,什么时候调,这样我们的业务类不仅得到了增强,还简化了代码。

当然,JDK的动态代理也有缺陷,不知道你发现了没有,这里的每个委托类都必须是要有接口的,也就是说JDK的动态代理依靠接口实现,要是我一个没有接口的类想被代理怎么办?

如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。请看下篇博客。

时间: 2024-10-09 22:21:14

谈谈java代理模式的认识二的相关文章

Java代理模式——静态代理模式

一:代理模式 代理模式的作用是:为其他对象提供一种代理以控制这个对象的访问.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 二:代理模式设计到的角色 抽象角色:声明真是对象和代理对象的共同接口(抽象类或接口). 代理角色:代理对象角色内部含有对真是对象的引用,从而可以操作真是对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能够代替真是对象.同时,代理对象可以在执行真实对象的操作时,附加其他操作,相当于对真是对象进行封装. 真实

java 代理模式详解

java 动态代理(JDK和cglib) 设计模式这东东每次看到就明白可过段时间又不能很流利的说出来,今天就用详细的比喻和实例来加深自己的理解(小弟水平不高有不对的地方希望大家能指出来). (1)代理这个词生活中有很多比如在街边卖手机卡.充公交地铁卡的小商店他们都起了代理的作用,java中的代理跟这些小店商的作用是一样的.再比如我想在淘宝上开个服装店但又没有货源怎么办,这时候我就要跟淘宝上某一卖家联系做他的代理.我跟我的商家都要卖衣服(就好比我们都继承了卖衣服的接口sellClothesInte

Java代理模式

Java代理模式分为静态代理和动态代理模式 静态代理模式比较简单,直接上图和代码: 代理模式类图如下: 在代理模式中的角色: ● 抽象对象角色:声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象. ● 目标对象角色:定义了代理对象所代表的目标对象. ● 代理对象角色:代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象:代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象.代理对象通常在客户端调用传递给目标对象之前或之后,执行某个

java代理模式学习

Java动态代理模式 1. 代理:一个角色代表别一个角色来完成某些特定的功能. 比如:生产商,中间商,客户这三者这间的关系 客户买产品并不直接与生产商打交道,也不用知道产品是如何产生的,客户只与中间商打交道,而中间商就可以对产品进行一些包装,提供一些售后的服务. 代理模式有三个角色: 1. 抽象主题角色 2. 代理主题角色 3. 实际被代理角色 其它类通过访问代理主题角色来访问实际被代理角色. 2. 下面我们来个一个静态代理的实现. 我以一个坦克为例. 抽象主题角色:Moveable Java代

从java 反射看延迟加载(代理模式)(二)

代理模式 代理模式使用代理对象完成用户请求,屏蔽用户对真实对象的访问.现实世界的代理人被授权执行当事人的一些事宜,无需当事人出面,从第三方的角度看,似乎当事人并不存在,因为他只和代理人通信.而事实上代理人是要有当事人的授权,并且在核心问题上还需要请示当事人. 在软件设计中,使用代理模式的意图也很多,比如因为安全原因需要屏蔽客户端直接访问真实对象,或者在远程调用中需要使用代理类处理远程方法调用的技术细节 (如 RMI),也可能为了提升系统性能,对真实对象进行封装,从而达到延迟加载的目的. 代理模式

Java 代理模式(二) Java中的动态代理

动态代理类 Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 1.Interface InvocationHandler 该接口中仅定义了一个方法: Object invoke(Object proxy, Method method, Object[] args) 在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组(无参时设置为null). 这个抽象方法在代理类中动态实现. 2

java 代理模式,观察者模式

代理模式1 [java] view plain copy import <a href="http://lib.csdn.net/base/17" class='replace_word' title="Java EE知识库" target='_blank' style='color:#df3434; font-weight:bold;'>Java</a>.lang.reflect.InvocationHandler; import java

Java 代理模式

代理模式的概念:为其他对象提供一种代理一控制对这个对象的访问. 应用场景:在开发中一些业务类中方法,除了需求的操作,还需要进行其他的非业务操作.比如提供给app的接口.除了接口要实现的业务逻辑,还要对用户的信息,设备的信息进行验证,参数的加密解密.这种在每个接口方法前都要调用的,和业务代码参在一起就会重复,累赘.可以通过代理类将这些经常使用的方法抽取出来.业务类只用关心业务操作,降低耦合. 静态代理 代理和被代理对象在代理前是确定的.他们都实现了相同的接口或者继承了相同的抽象类. 动态代理 动态

Java代理模式(Proxy模式)

理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理. 设计模式中定义:为其他对象提供一种代理以控制对这个对象的访问. 为什么要使用代理模式 授权机制 不同级别的用户对同一对象拥有不同的访问权利,如Jive论坛系统中,就使用Proxy进行授