静态代理与动态代理的简单使用

代理模式(Proxy Pattern)是一种比较常见的设计模式,在很多场合都会被用到。

所谓代理指的是让其他的类代替完成一些任务(执行一些方法等),在软件开发中代理模式具有非常重要的作用,面向切面编程(AOP)便是基于代理模式运作的编程范式。

下面介绍一下其中的静态代理与动态代理,基于Java语言。

静态代理:

首先由一个HelloWorld接口,其中有一个方法,print

public interface HelloWorld {
    void print();
}

接下来是实现了HelloWorld接口的HelloWorldImpl类

public class HelloWorldImpl implements HelloWorld {
    @Override
    public void print() {
        System.out.println("Hello World");
    }
}

如果想要在方法的开头或者结尾做一些事情,例如打印日志之类或者处理一些校验逻辑之类的的,如果将其也写入print方法中会使得代码中业务代码与非业务代码交织在一起,这样不是一种很好的做法。

我们可以使用静态代理来做一些"手脚",完成这样的需求。

public class HelloWorldProxy implements HelloWorld {
    private final HelloWorld helloWorld;
    public HelloWorldProxy(HelloWorld helloWorld) {
        this.helloWorld = helloWorld;
    }
    @Override
    public void print() {
        before();
        helloWorld.print();
        after();
    }
    private void before() {
        System.out.println("Begin");
    }
    private void after() {
        System.out.println("End");
    }
}

最后,我们编写代码,测试一下

public class HelloWorldTest {
    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorldProxy();
        helloWorld.print();
    }
}

程序将打印

Begin
Hello World
End

之所以上面的代理代码被称为静态代理是因为这个是在编译阶段就已经能够确定的代理关系。

静态代理具有代理模式的优点就是可以做到隔离业务代码与非业务代码

静态代理的主要缺点是一个委托类对应于一个代理类,并且需要为每一个需要委托的方法编写相应的代理方法,对于项目中需要大量用到代理模式的情况,静态代理会增加非常多的代码量

此外,由于代理类与委托类都实现了同样的接口,假设接口需要变动,代理类也需要同步变动,这样对于软件项目维护也会增加不少的工作量与难度

接下来介绍上面的例子如何改成使用动态代理

动态代理:

首先原来的HelloWorldProxy类可以删掉了

编写HelloWorldInvocationHandler类,实现java.lang.reflect.InvocationHandler类,作为HelloWorld的调用处理器

public class HelloWorldInvocationHandler implements InvocationHandler {
    private Object obj;

    public HelloWorldInvocationHandler(Object obj) {
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(obj, args);
        after();
        return result;
    }

    private void before() {
        System.out.println("Begin");
    }

    private void after() {
        System.out.println("End");
    }
}

接下来,改一下原来的HelloWorldTest类

public class HelloWorldTest {
    public static void main(String[] args) {
        HelloWorld helloWorld = new HelloWorldImpl();

        InvocationHandler handler = new HelloWorldInvocationHandler(helloWorld);

        HelloWorld proxy = (HelloWorld) Proxy.newProxyInstance(
                helloWorld.getClass().getClassLoader(),
                helloWorld.getClass().getInterfaces(),
                handler);

        proxy.print();
    }
}

运行HelloWorldTest,可以得到与上面静态代理同样的结果

Begin
Hello World
End

上面的代码仍然有些繁琐,可以有两种方式简化一下获取代理的代码,一种是做一个HelloWorld代理的工厂,每一次从工厂中拿上面代码中的proxy,还有一种是在HelloWorldInvocationHandler类中增加一个getProxy方法。

稍稍总结一下动态代理的优缺点

相比静态代理,一个非常显著的优点是动态代理可以在自定义调用处理器统一处理委托类的方法,而不必一个个编写。

而动态代理有一个缺点,那就是只能代理基于接口的类,而无法代理没有接口的委托类。关于这一点,可以使用CGLib类库来做到代理无接口类。

本文参考链接:

http://layznet.iteye.com/blog/1182924

http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/

时间: 2024-10-25 10:46:29

静态代理与动态代理的简单使用的相关文章

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

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

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

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

静态代理、动态代理

代理模式最大的优势就是能够解耦,在spring中也是广泛使用.spring中一个重要的特性就是aop,aop是个啥东西呢?其实很简单,比如现在有个业务方法,那这个业务方法很重要,涉及到非常重要的业务数据,那对于广大企业应用来说,为了以后能够及时的定位问题,需要记录相关入参以及出参到日志表. 但是对于企业应用来说,需要记录日志的地方应该是蛮多的,如果每个方法中都手动的去写这些记录日志的东西,就会特别的冗余,那使用代理模式就可以解决. 一.静态代理 1.User接口 package com.ty.s

java中静态代理和动态代理

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

静态代理与动态代理

记得刚接触代理,是在大话设计模式,最近在技术总结和学些java的过程又接触到静态代理和动态代理,尤其是动态代理,在学习AOP时,用到了动态代理,下面我用一些例子来对静态代理和动态代理做个总结. 其实用了代理之后最大的好处就是隐藏了真实类(委托类),这样更加安全,而静态代理和动态代理最大的区别就是,静态代理的代理类是程序员自己写的,在程序运行之前就已经存在的,而动态代理则是在程序运行时动态生成的,而且因为动态代理更加灵活,也常被应用. 首先先用一张UML图来理解一下代理是怎么回事? 其实静态代理就

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

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

spring静态代理和动态代理

本节要点: Java静态代理 Jdk动态代理 1 面向对象设计思想遇到的问题 在传统OOP编程里以对象为核心,并通过对象之间的协作来形成一个完整的软件功能,由于对象可以继承,因此我们可以把具有相同功能或相同特征的属性抽象到一个层次分明的类结构体系中.随着软件规范的不断扩大,专业化分工越来越系列,以及OOP应用实践的不断增多,随之也暴露了一些OOP无法很好解决的问题. 现在假设系统中有三段完全相似的代码,这些代码通常会采用"复制"."粘贴"方式来完成,通过这种方式开发

Atitit 代理CGLIB 动态代理 AspectJ静态代理区别

Atitit 代理CGLIB 动态代理 AspectJ静态代理区别 1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表:而动态代理则以 spring AOP 为代表 1 1.2. JDK动态代理是模拟接口实现的方式,cglib是模拟子类继承的方式1 1.3. CGLIB代理模式的缺点 在static和final方法上应用横切关注点也是无法做到的.2 1.1. AOP 代理主要分为静态代理和动态代理两大类,静态代理以 AspectJ 为代表:而动态代理则以 

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

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