Java基础:静态代理和动态代理

转载请注明出处:jiq?钦‘s
technical Blog

一、静态代理:

假设原来有一个实现了指定接口/抽象类的子类:

class RealSubject implements Subject{
    public void request(){
        System.out.print("real request handling\n");
    }
} 

现在有两种情况会发生:

1新的代码需要调用Subject接口,但是需要给每个接口加入新代码(比如日志记录、权限控制等);

2旧的代码已经使用了Subject接口,需要不改动现有代码情况下加入新的代码(比如日志记录,权限控制);

对于这这两种情况,最直接的想法就是重新写一个代理类,同样实现Subject接口,针对RealSubject的所有接口进行封装,加入新的代码:

/************************************************
 * 静态代理,封装(控制)request方法的访问
 ************************************************/
class StaticProxySubject implements Subject{
    private RealSubject realSubject;    //组合被代理的对象
    public void request(){
        //do some thing else...
        if(realSubject == null){
            realSubject = new RealSubject();
        }
        realSubject.request();          //真正的request调用
        //do some thing else...
    }     

这里需要注意,第二种情况即旧代码要在不改动的情况下使用新建的这个静态代理类,在写代码时需要满足两点:

1面向Subject接口编程;

2创建Subject实例时采用工厂模式,通过读取配置文件决定反射哪个类的实例;

这样在创建一个新的静态代理时,才可以通过修改配置文件无缝集成到现有代码,修改行为而无需改动现有代码。

//通过静态代理来访问对象
Subject proxy = new StaticProxySubject();
proxy.request(); 

二、面向方面编程(AOP)

其实上面所说的第二种情况就是实现面向方面的编程的方式之一(将切面代码至于原始方法外面),在不改动现有代码的情况下,为所有业务横向插入公共逻辑(常见的如安全、事务控制、日志等),将交叉业务模块化。

三、动态代理

很明显静态代理有个大问题,就是一旦原始目标类接口过多,要为每个接口进行静态代理封装,那代价也很大。

因此Java中提出一个动态代理的概念,动态代理需要实现Java中的InvocationHandler接口:

/***********************************************************
 * 动态代理. java.lang.reflect包中有自己的代理支持,利用这个包
 * 你可以在运行时动态创建一个代理类,实现一个或者多个接口,并将
 * 方法的调用转发到你所指定的类。
 * 因为实际的代理类是在运行时创建的,所以我们称这个技术为动态代理。
 * ***********************************************************/
class DynamicProxySubject implements InvocationHandler{
    private Object realSubject;         //组合被代理的对象  

    public DynamicProxySubject(Object realSubject){
        this.realSubject = realSubject;
    }  

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //do some thing else...
        return method.invoke(realSubject, args);  //调用对象realSubject的method方法
        //do some thing else...
    }
}  

然后通过JavaProxy类提供的静态方法newProxyInstance()可以创建一个动态代理实例:

RealSubject real = new RealSubject();
Subject subject = (Subject) Proxy.newProxyInstance(
                real.getClass().getClassLoader(),   //定义代理类的类加载器
                real.getClass().getInterfaces(),    //代理类要实现的接口列表
                new DynamicProxySubject(real));     //指派方法调用的调用处理程序
subject.request();  

(1)其中最后一个参数是动态代理类对象,组合了其真正要代理的类。

(2)倒数第二个参数需要传递要代理的真正的类的接口信息(Class信息),即Subject接口信息,这样返回的代理就是Subject类型的。

这样每次调用返回的Subject类型代理对象的接口时,都会转换为针对动态代理类中invoke方法的调用,在invoke方法中又调用真正代理的类的方法,我们可以将横切代码(日志、权限控制等)至于invoke方法中实现AOP。

四、动态代理原理

关键在于创建动态代理的newProxyInstance方法:

RealSubject real = new RealSubject();
Subject subject = (Subject) Proxy.newProxyInstance(
                real.getClass().getClassLoader(),   //定义代理类的类加载器
                real.getClass().getInterfaces(),    //代理类要实现的接口列表
                new DynamicProxySubject(real));     //指派方法调用的调用处理程序
subject.request();  

倒数第二个参数是要代理的类的接口(Subject)的Class对象。第三个参数是动态代理类。

newProxyInstance方法返回一个类对象,该类实现了Subject接口,同时继承自JavaProxy类:

classProxy{
    InvocationHandler h=null;
    protected Proxy(InvocationHandler h) {
        this.h = h;
    }
    ...
}

这个自动生成的类为什么能够实现Subject接口,答案是反射机制。

通过反射可以知道该接口所有方法,然后重写这些方法,简单地调用父类Proxy的动态代理属性的invoke方法即可。

publicfinal void request() {
        try {
            super.h.invoke(this,m3, null);
            return;
        } catch (Error e) {
        } catch (Throwable throwable) {
            throw newUndeclaredThrowableException(throwable);
        } 

    }

由此可见,返回的代理对象向上转换为Subject类型,调用其方法(自动生成)时,在内部转换为针对动态代理类的invoke方法的调用。

时间: 2024-10-05 23:57:28

Java基础:静态代理和动态代理的相关文章

Java基础之反射和动态代理

1,反射是依赖于Class对象,然后根据Class对象,去操作该类的资源的.Class对象是发射的基石! 问题1:人这类事物用什么表示?汽车这类事物用什么表示>计算机文件用什么表示?有如此多的事物该用什么表示? 答案:Person类,Car类,File类,这么多的类也是一类事物,这类事物用Class表示. 问题2:Person类的对象,我们知道代表一个具体的人.那么Class类的对象,又代表什么? 一个类,在硬盘上表示一个.class文件,JVM启动的时候,把文件加载到内存上,占用一片空间,称为

Java基础-静态代理以及动态代理

动态代理: 在了解动态代理之前,先对代理有一个认识. 代理模式是Java常见的设计模式之一.所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理,来间接的调用实际的对象. 打个比方:你买火车票的时候,并不直接花钱购买, 而是将钱预先垫付到抢票软件上, 使抢票软件为你购买, 你要做的行为就是买票,抢票软件就是你的代理 代理对象控制对被代理对象的访问: 这是代理的通用模型图 Subject:定义了被代理角色和代理角色的共同接口或者抽象类,也就是subject中定义了共同接口opration

JAVA学习篇--静态代理VS动态代理

本篇博客的由来,之前我们学习大话设计,就了解了代理模式,但为什么还要说呢? 原因: 1,通过DRP这个项目,了解到了动态代理,认识到我们之前一直使用的都是静态代理,那么动态代理又有什么好处呢?它们二者的区别是什么呢? 2,通过学习动态代理了解到动态代理是一种符合AOP设计思想的技术,那么什么又是AOP? 下面是我对它们的理解! 代理Proxy: Proxy代理模式是一种结构型设计模式,主要解决的问题是:在直接访问对象时带来的问题 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对

java 代理模式(静态代理、动态代理、Cglib代理) 转载

Java的三种代理模式 1.代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法 代理模式最大的特点就是代理类和实际业务类实现同一个接口(或继承同一父类),代理对象持有一个实际对象的引用,外部调用时操作的是代理对象,而在代理对象的内部实现中又会去调

java中静态代理和动态代理

一.概述 代理是一种模式,提供了对目标对象的间接访问方式,即通过代理访问目标对象.如此便于在目标实现的基础上增加额外的功能操作,前拦截,后拦截等,以满足自身的业务需求,同时代理模式便于扩展目标对象功能的特点也为多人所用. 按照代理的创建时期,代理类可以分为两种: 静态:由程序员创建代理类或特定工具自动生成源代码再对其编译.在程序运行前代理类的.class文件就已经存在了. 动态:在程序运行时运用反射机制动态创建而成. 我们根据加载被代理类的时机不同,将代理分为静态代理和动态代理.如果我们在代码编

深入浅出java静态代理和动态代理

首先介绍一下,什么是代理: 代理模式,是常用的设计模式.特征是,代理类与委托类有相同的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类.以及事后处理消息. 代理类和委托类,存在着关联关系.代理类的对象本身并不真正实现服务,知识通过调用委托类的对象的相关方法. 代理类可以分为两种:静态代理和动态代理. 静态代理: 代理类是由程序员创建,或由工具生成的代码 编译成的.在程序运行前,代理类的 *.class文件已经存在了.直接就可以运行 . 动态代理: 动态代理的代理类.没有直接由

java静态代理与动态代理

原文链接:http://www.orlion.ga/207/ 一.代理模式 代理模式是经常用到的设计模式,代理模式是给指定对象提供代理对象.由代理对象来控制具体对象的引用. 代理模式涉及到的角色: 抽象主题角色:声明了代理主题和真实主题的公共接口,使任何需要真实主题的地方都能用代理主题代替. 代理主题角色:含有真实主题的引用,从而可以在任何时候操作真实主题,代理主题功过提供和真实主题相同的接口,使它可以随时代替真实主题.代理主题通过持有真实主题的引用,不但可以控制真实主题的创建或删除,可以在真实

【Java】代处理?代理模式 - 静态代理,动态代理

>不用代理 有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码. 这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果.(至于为什么不直接用+号运算,见[Java]Float计算不准确) package com.nicchagil.study.java.demo.No09代理.No01不用代理; import java.math.BigDecimal; public class FloatCalculator { public float add(fl

java静态代理与动态代理简单分析

原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/5860749.html 1.动态代理(Dynamic Proxy) 代理分为静态代理和动态代理,静态代理是在编译时就将接口.实现类.代理类一股脑儿全部手动完成,但如果我们需要很多的代理,每一个都这么手动的去创建实属浪费时间,而且会有大量的重复代码,此时我们就可以采用动态代理,动态代理可以在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能. 其实方法直接调用就可以完成功能,为什么

【java项目实战】代理模式(Proxy Pattern),静态代理 VS 动态代理

这篇博文,我们主要以类图和代码的形式来对照学习一下静态代理和动态代理.重点解析各自的优缺点. 定义 代理模式(Proxy Pattern)是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用. 代理模式不会改变原来的接口和行为,仅仅是转由代理干某件事,代理能够控制原来的目标,比如:代理商,代理商仅仅会买东西,但并不会改变行为.不会制造东西. 让我们通过以下的代码好好理解一下这句话. 分类 静态代理和动态代理 静态代理 静态代理类图 代码演示样例 接口 pac