`
mcj8089
  • 浏览: 193624 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java中的静态代理和动态代理

    博客分类:
  • Java
阅读更多

Java中的静态代理和动态代理

一、引入代理的概念

      我叫蒙林,在北京租了一间房子。昨天我有事去了广东,当我到了广东后,房东王小三打电话给我说今天该交房租了(合同上写的是今天交房租,且过期不交房租将产生滞纳金),那么我怎么办呢? 于是我打电话给北京的朋友黄河,让他先替我把房租交给房东,那么黄河是以我的名义交的房租。

      那么在这一事件中,黄河就是我蒙林的代理(英文为Proxy),当我不方便办理某一件事情的时候,代理可以替我完成。黄河(我的代理)和我都有交房租的这一能力。

 

二、Java中的代理

      从面向对象的角度来说,蒙林和黄河各为一个类,他们都有一个交房租的功能,因此我可以让他们都实现同一接口,接口中定义二者的共同功能。

涉及到的类有:

MengLin.java  ——蒙林

HuangHe_Proxy.java  ——黄河

Function.java  —— 功能类(定义二者共同的方法)

Test.java —— 测试类

 

 

package Proxy;

public abstract class Function {
	// 二者都可以交房租
	public abstract void jiaoFangZu();

}
  
package Proxy;

public class HuangHe_Proxy extends Function {

	// 黄河是代理,他要代理谁?
	private Function who = null;

	// 通过构造函数确定代理谁
	public HuangHe_Proxy(Function who) {
		this.who = who;
	}

	// 如果我指定who为蒙林,那么黄河交房租实际上是蒙林交房租, 但是交房租之前黄河可以做些其他事情
	@Override
	public void jiaoFangZu() {
		chiFan();
		quQian();
		who.jiaoFangZu();
	}

	public void quQian() {
		System.out.println("先去银行取2000块钱。");
	}

	public void chiFan() {
		System.out.println("吃饱了再说。");
	}
}

 

package Proxy;

public class MengLin extends Function {

	@Override
	public void jiaoFangZu() {
		System.out.println("房东,给你下个月的房租。");
	}

}

 

public class Test {

	public static void main(String[] args) {
		// 蒙林和黄河都继承Function类
		Function mengLin = new MengLin();
		Function huangHe = new HuangHe_Proxy(mengLin);
		huangHe.jiaoFangZu();
	}
}
   

      总结:上面讲的是静态代理模式,你只需要编写代理类、被代理类和他们的功能类。Spring中的AOP(面向切面编程)在调用一个方法前后可以做一些其他的处理(比如记录日志),它就是通过代理模式实现的。

 

三、什么是动态代理

      讲完静态代理,该说说动态代理了。动态代理不需要像静态代理那样自己定义代理类,JVM提供了两个API帮助你在程序运行过程中生成代理,这就是“动态”的概念。

      这两个API分别是java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy。

 

InvocationHandler源码如下:

 

public interface InvocationHandler {

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

 将来调用代理类中的方法时,实际上是调用invoke方法。

 

Proxy有一个方法

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

 

通过这个方法就可以得到一个代理类了。 其中  loader 是蒙林的类加载器,  interfaces是蒙林实现的接口(如果蒙林没有实现接口那么将发生异常),  h 是一个  InvocationHandler。

 

下面通过程序说明动态代理的实现。

涉及到的类有:

MengLin.java  ——蒙林(同静态代理)

Function.java  —— 功能类(必须改为接口)

Handler.java —— 实现InvocationHandle接口

Test.java —— 测试类

 

package Proxy;

public interface class Function {
	 
	public abstract void jiaoFangZu();

}
 

 

package Proxy;

import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class Handler implements InvocationHandler { // 被代理者 private Object beProxyer = null; public Handler(Object obj) { this.beProxyer = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before call method: " + method); Object result = method.invoke(beProxyer, args); System.out.println("after call method: " + method); return result; } }

 

package Proxy;

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

public class Test {

	public static void main(String[] args) {
		
		Function mengLin = new MengLin();
		// 定义InvocationHandler
		InvocationHandler handler = new Handler(mengLin);
		// 生成代理类,返回类型为Object
		Object object = Proxy.newProxyInstance(mengLin.getClass().getClassLoader(), mengLin.getClass().getInterfaces(), handler);
		// 将代理转换为被代理类类型
		MengLin mengLinProxy = (Function)object;
		// 现在调用mengLinProxy.jiaoFangZu()函数等同于mengLin.jiaoFangZu()
		mengLinProxy.jiaoFangZu();
	}
}

 

 

   总结:上面讲的是动态代理模式,你只需要编写被代理类和他们的功能接口,然后通过Proxy类和InvocationHandler接口生成动态代理类。

 

 四、应用

下面,通过动态代理实现拦截器功能。

 

package com.biocjm;

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

public class DynamicProxyUtil implements InvocationHandler {

	/** the Object will be proxyed */
	private Object proxyer = null;

	/**
	 * a interceptor, with it, you can do something you want before or after
	 * execute a proxyer's method
	 */
	private Interceptor interceptor = null;

	/**
	 * this is a constructor, via it the util can get a proxyer
	 * 
	 * @param proxyer-object will be proxyed
	 */
	public DynamicProxyUtil(Object proxyer) {
		this.proxyer = proxyer;
	}

	/**
	 * set a interceptor
	 * 
	 * @param interceptor
	 */
	public void setInterceptor(Interceptor interceptor) {
		this.interceptor = interceptor;
	}

	/**
	 * you can change the proxyer during your use of DynamicProxyUtil
	 * 
	 * @param proxyer-object will be proxyed
	 */
	public void setProxyer(Object proxyer) {
		this.proxyer = proxyer;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		beforeMethod();
		Object result = method.invoke(proxyer, args);
		afterMethod();
		return result;
	}

	/**
	 * get a Proxy Object with the same interface with proxyer
	 * 
	 * @return a Proxy
	 */

	public Object getProxy() {
		return Proxy.newProxyInstance(proxyer.getClass().getClassLoader(), proxyer.getClass().getInterfaces(), this);
	}

	/** do before the proxyer's method execute */
	public void beforeMethod() {
		if (interceptor != null) {
			interceptor.doBefore();
		}
	}

	/** do after the proxyer's method execute */
	public void afterMethod() {
		if (interceptor != null) {
			interceptor.doAfter();
		}
	}

	interface Interceptor {

		public void doBefore();

		public void doAfter();

	}
}
 
package com.biocjm;

import com.biocjm.DynamicProxyUtil.Interceptor;

public class Test {

	public static void main(String[] args) {
		dproxy();
	}

	// 动态代理工具类测试
	public static void dproxy() {
		Interceptor interceptor = new Interceptor() {

			@Override
			public void doBefore() {
				System.out.println("before method.");
			}

			@Override
			public void doAfter() {
				System.out.println("after method. ");
			}
		};
		DynamicProxyUtil dynamicProxyUtil = new DynamicProxyUtil(interceptor);
		dynamicProxyUtil.setInterceptor(interceptor);

		Object dyProxy = dynamicProxyUtil.getProxy();
		// 切记,动态代理是基于借口编程的, 因此被代理类一定要实现至少一个接口,否则在类型转换时将出现异常
		Interceptor interceptor2 = (Interceptor) dyProxy;
		interceptor2.doAfter();
	}
}

 

 

 

 

 

 

 

 

 

 

1
0
分享到:
评论

相关推荐

    JAVA静态代理和动态代理

    Java提供了两种主要的代理实现方式:静态代理和动态代理。 **静态代理** 静态代理是程序员手动创建代理类并实现与目标对象相同的接口。代理类和目标类都必须实现相同的接口,这样代理类就可以在调用目标对象方法的...

    Java静态代理和动态代理

    Java的代理模式通过代理类提供了对委托类的扩展和控制,静态代理适合对已有代码不做修改的情况,而动态代理则提供了更高的灵活性和扩展性。在实际应用中,应根据项目需求和性能考虑选择静态代理或动态代理。对于需要...

    Java设计模式——代理设计模式(静态代理和动态代理)

    代理设计模式分为静态代理和动态代理两种类型。 ### 静态代理 静态代理是在编译时就已经确定了代理关系,代理类和真实类的关系是硬编码在代理类中的。下面我们将详细介绍静态代理的实现方式: 1. **定义接口**:...

    Java静态代理与动态代理demo

    Java提供了两种实现代理模式的方式:静态代理和动态代理。 **静态代理** 静态代理是在编译时就已经确定了代理类,通过继承或实现目标接口来创建代理类。以下是一个简单的静态代理实现示例: ```java // 目标接口 ...

    java 静态代理和动态代理学习实例源码

    代理模式通常分为静态代理和动态代理两种类型,这两种代理方式各有特点,适用于不同的场景。 **静态代理** 静态代理是通过程序员手动创建一个代理类来实现的。代理类和真实目标类需要实现相同的接口,以便代理类...

    java静态代理、动态代理、装饰设计模式

    Java提供了两种实现代理的主要方式:静态代理和动态代理。 **静态代理** 静态代理是最基础的形式,它需要程序员手动创建一个代理类,该类实现了与目标类相同的接口。代理类持有目标类的引用,并在调用目标类方法...

    Java中的代理模式--静态代理和动态代理

    Java中的代理模式--静态代理和动态代理 Java中的代理模式--静态代理和动态代理

    java静态代理和动态代理详解

    在Java中,代理主要分为静态代理和动态代理。 1. 静态代理: 静态代理是在编译时就已经明确代理类与被代理类关系的一种方式。为了实现静态代理,我们需要手动创建一个代理类,这个代理类通常会实现与被代理类相同的...

    Java 静态代理模式

    Java静态代理模式是一种设计模式,它允许我们为一个对象提供一个代理,以便增强或扩展其功能,同时不改变原有对象的代码。在Java中,静态代理是通过在代理类中显式实现目标接口来实现的。下面将详细介绍静态代理模式...

    java静态代理和动态代理

    总结来说,Java中的静态代理和动态代理都提供了在调用实际对象的方法时添加额外逻辑的能力。静态代理更易于理解,但在需要为多个接口或大量接口创建代理时,代码会变得冗长。而动态代理则更灵活,可以在运行时动态地...

    静态代理和动态代理Demo

    静态代理和动态代理是两种常见的代理模式,它们在Java中有着广泛的应用,特别是在SpringBoot等框架中。本资源提供了一个简单的Java实现,适用于JDK1.8版本,并经过了验证,对初学者理解设计模式具有指导意义。 静态...

    静态代理和动态代理

    根据实现方式的不同,代理模式可以分为静态代理和动态代理两种。 ### 静态代理 静态代理是在编译时就已经确定了代理关系。我们需要创建一个代理类,该类实现与目标对象相同的接口,并在代理类的方法中调用目标对象...

    Spring的静态代理和动态代理

    本篇我们将深入探讨Spring中的静态代理和动态代理,这两种代理模式在实际开发中都有广泛的应用。 首先,让我们理解什么是代理。代理模式是一种设计模式,它为一个对象提供一个代理以控制对这个对象的访问。在Spring...

    包含静态代理和动态代理demo代码

    在这个“包含静态代理和动态代理demo代码”的压缩包中,我们可能会看到两种常见的Java代理实现方式的示例:静态代理和动态代理。 首先,我们来详细讲解静态代理。在静态代理中,代理类和真实类(目标类)都是在编译...

    静态代理和动态代理的讲解和案例,有详细的注释

    本教程将深入探讨静态代理和JDK动态代理的概念、工作原理以及如何实现。 ### 静态代理 静态代理是在编译时就确定了代理类和目标类的关系。代理类和目标类通常都需要实现相同的接口,以便于在代理类中调用目标类的...

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理)

    Java 动态代理详解(代理模式+静态代理+JDK动态代理+CGLIB动态代理) Java 动态代理是 Java 编程语言中的一种强大工具,广泛应用于 Spring AOP、Hibernate 数据查询、测试框架的后端 mock、RPC 远程调用、Java 注解...

    JAVA JDK静态代理、动态代理、CGlib代理的代码演示

    Java提供了两种主要的代理实现方式:JDK静态代理和动态代理,另外还有第三方库如CGlib提供的代理实现。下面我们将详细探讨这些代理技术,并通过代码演示来理解它们的工作原理。 ### 1. JDK静态代理 静态代理是我们...

Global site tag (gtag.js) - Google Analytics