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

>不用代理

有时候,我希望在一些方法前后都打印一些日志,于是有了如下代码。

这是一个处理float类型加法的方法,我想在调用它前打印一下参数,调用后打印下计算结果。(至于为什么不直接用+号运算,见【Java】Float计算不准确

package com.nicchagil.study.java.demo.No09代理.No01不用代理;

import java.math.BigDecimal;

public class FloatCalculator {

    public float add(float a, float b) {

        BigDecimal b1 = new BigDecimal(a + "");
        BigDecimal b2 = new BigDecimal(b + "");
        float f = b1.add(b2).floatValue();

        return f;

    }
}

我想在它运行前后打印,最直接的方式就是调用时打印了

package com.nicchagil.study.java.demo.No09代理.No01不用代理;

public class Call {

    public static void main(String[] args) {
        float f1 = 1f;
        float f2 = 1f;

        System.out.println("f1 -> " + f1 + ", f2 -> " + f2);
        float result = new FloatCalculator().add(f1, f2);
        System.out.println("result -> " + result);
    }
}

看到这日志,我很欣慰!

f1 -> 1.0, f2 -> 1.0
result -> 2.0

>静态代理

随着项目变大,调用此方法的地方变得越来越多,如果有10个调用的地方,我岂不是要写100次打印的方法。

这时,静态代理的方式能帮助我们。

定义个接口

package com.nicchagil.study.java.demo.No09代理.No02静态代理;

public interface ICalculator {

    /**
     * <p>add</p>
     */
    public float add(float a, float b);

}

真实业务类

package com.nicchagil.study.java.demo.No09代理.No02静态代理;

import java.math.BigDecimal;

public class FloatCalculator implements ICalculator {

    @Override
    public float add(float a, float b) {

        BigDecimal b1 = new BigDecimal(a + "");
        BigDecimal b2 = new BigDecimal(b + "");
        float f = b1.add(b2).floatValue();

        return f;

    }

}

代理类,这个类中,处理执行实际业务,还一并捆绑打印日志的任务

package com.nicchagil.study.java.demo.No09代理.No02静态代理;

public class FloatCalculatorProxy implements ICalculator {

    ICalculator c = null;

    /**
     * 构造方法
     * @param c    需被代理的对象
     */
    public FloatCalculatorProxy(ICalculator c) {
        super();
        this.c = c;
    }

    @Override
    public float add(float f1, float f2) {
        System.out.println("f1 -> " + f1 + ", f2 -> " + f2);

        float result = this.c.add(f1, f2);

        System.out.println("result -> " + result);
        return result;
    }

}

然后,我们调用时,只需调用代理类,不仅计算得结果,日志也乖乖地出来了

package com.nicchagil.study.java.demo.No09代理.No02静态代理;

public class Call {

    public static void main(String[] args) {
        System.out.println("代理的对象:");
        ICalculator c2 = new FloatCalculatorProxy(new FloatCalculator());
        c2.add(1f, 1f);
    }

}

看到日志,我很镇静

代理的对象:
f1 -> 1.0, f2 -> 1.0
result -> 2.0

>动态代理

如果现在不仅FloatCalculator这个类需要打印日志,还有其他各种类也需要打印日志,那么我们岂不是要写好多个代理类了?

这时候,Java API拍案而起,提出动态代理。通过反射机制为我们实现动态代理。

接口类(ICalculator)、真实业务类(FloatCalculator)如同静态代理,不再重复

调用处理类

package com.nicchagil.study.java.demo.No09代理.No03动态代理;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicProxyHandler implements InvocationHandler {

    private Object proxied = null;

    public DynamicProxyHandler(Object proxied) {
        this.proxied = proxied;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("Clazz    -> " + proxy.getClass());
        System.out.println("method    -> " + method);
        for (int i = 0; i < args.length; i++) {
            System.out.println("args[" + i + "]    -> " + args[i]);
        }

        Object result = method.invoke(proxied, args);

        System.out.println("result    -> " + (result != null ? result.toString() : ""));
        return result;
    }

}

调用类

package com.nicchagil.study.java.demo.No09代理.No03动态代理;

import java.lang.reflect.Proxy;

import com.nicchagil.study.java.demo.No09代理.No02静态代理.FloatCalculator;
import com.nicchagil.study.java.demo.No09代理.No02静态代理.ICalculator;

public class Call {

    public static void main(String[] args) {
        /* 代理的对象 */
        System.out.println("代理的对象:");
        ICalculator c2 = (ICalculator)Proxy.newProxyInstance(ICalculator.class.getClassLoader(),
                new Class[] {ICalculator.class}, new DynamicProxyHandler(new FloatCalculator()));
        c2.add(1f, 1f);
    }

}

日志

代理的对象:
Clazz    -> class $Proxy0
method    -> public abstract float com.nicchagil.study.java.demo.No09代理.No02静态代理.ICalculator.add(float,float)
args[0]    -> 1.0
args[1]    -> 1.0
result    -> 2.0

暂时完毕。

时间: 2024-10-23 16:22:29

【Java】代处理?代理模式 - 静态代理,动态代理的相关文章

23种设计模式----------代理模式(三) 之 动态代理模式

(上一篇)种设计模式----------代理模式(二) 当然代理模式中,用的最广泛的,用的最多的是  动态代理模式. 动态代理:就是实现阶段不用关系代理是哪个,而在运行阶段指定具体哪个代理. 抽象接口的类图如下: --图来自设计模式之禅 所以动态代理模式要有一个InvocationHandler接口 和 GamePlayerIH实现类.其中 InvocationHandler是JD提供的动态代理接口,对被代理类的方法进行代理. 代码实现如下 抽象主题类或者接口: 1 package com.ye

java 代理模式二:动态代理

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

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

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

Java类型信息与应用--动态代理

Java类型信息与应用--动态代理 本文结构 一.前言 二.为什么需要RTTI 三.RTTI在java中的工作原理 四.类型转化前先做检测 五.动态代理 六.动态代理的不足 一.前言 运行时信息使你可以在程序运行时发现和使用类型信息 Java在运行时识别对象和类的信息的方式: 1.一种是RTTI,它假定我们在编译时已经知道了所有的类型. 2.另一种是"反射"机制,它允许我们在运行时发现和使用类的信息. 这带来的好处是,你可以在程序运行时发现和使用类型信息 二.为什么需要RTTI 以多态

spring AOP 代理(静态与动态)

一.没有代理模式 缺点: 1.工作量特别大,如果项目中有多个类,多个方法,则要修改多次. 2.违背了设计原则:开闭原则(OCP),对扩展开放,对修改关闭,而为了增加功能把每个方法都修改了,也不便于维护. 3.违背了设计原则:单一职责(SRP),每个方法除了要完成自己本身的功能,还要计算耗时.延时:每一个方法引起它变化的原因就有多种. 4.违背了设计原则:依赖倒转(DIP),抽象不应该依赖细节,两者都应该依赖抽象.而在Test类中,Test与Math都是细节. 假设需实现一个计算的类Math.完成

代理模式---静态代理

一,静态代理介绍 了解设计模式中的代理模式的同学应该都知道如果想要为被代理类生成代理,需要让代理类和被代理类共同实现同一个接口,在代理类中增加额外逻辑来实现代理模式,这种方式在编译期间就已经确认了哪个类是代理类,被代理的又是哪个类,这都是需要开发人员在编译之前就编写好的,是为静态 1,代理模型的角色分析 抽象角色:一般会使用抽象类或者接口实现 真实角色:实体类,被代理的角色 代理角色:代理真实角色,而且可以附属一些其他操作 使用角色:使用代理角色进行操作 2,静态代理模式的优点 可以使真实角色更

zbb20180930 代理模式 -静态代理-jdk动态代理-cglib动态代理

CGLIB与JDK动态代理区别 区别: java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理.而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理. 1.如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2.如果目标对象实现了接口,可以强制使用CGLIB实现AOP 3.如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB

代理模式-静态代理与动态代理

简介 首先感谢沽泡学院 tom 老师 代理模式是一种结构型模式 代理模式就是代理对象帮被代理对象处理一些问题, 类似中介, 客户只要结果, 中介怎么搞是他的事儿, 他可能再处理过程中赚外快什么的 代理模式的应用: spring中的aop, 日常工作中记录日志, 统计时间,权限控制等 这里我们使用一个客户端代理访问google举例, 具体细节可能不合适, 意会.意会.意会... 静态代理 /** * 一个服务器接口, 服务器有很多功能, 可以用来路由, 建站等... */ public inter

java 反射之静态and动态代理

首先说一下我们什么情况下使用代理? (1)设计模式中有一个设计原则是开闭原则,是说对修改关闭对扩展开放,我们在工作中有时会接手很多前人的代码,里面代码逻辑让人摸不着头脑(sometimes the code is really like shit),这时就很难去下手修改代码,那么这时我们就可以通过代理对类进行增强. (2)我们在使用RPC框架的时候,框架本身并不能提前知道各个业务方要调用哪些接口的哪些方法 .那么这个时候,就可用通过动态代理的方式来建立一个中间人给客户端使用,也方便框架进行搭建逻