java实现简单的动态代理

本文介绍如何使用Java实现动态代理,包括静态代理的基本概念与实现,以及动态代理的原理与具体步骤。通过示例展示了如何利用动态代理在方法调用前后添加额外的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java实现简单的动态代理

先写一个简单的例子来说明为什么需要代理。
    1.编写接口UserManager.java
package proxy;

public interface UserManager {
	
	public void addUser(int id, String name, int age);
	
	public void deleteUser(int id);
	
	public String getUserName(int id);
}
2.编写实现类UserManagerImpl.java
package proxy;

public class UserManagerImpl implements UserManager {

	@Override
	public void addUser(int id, String name, int age) {
		System.out.println("------------addUser()-----------");
	}

	@Override
	public void deleteUser(int id) {
		System.out.println("------------deleteUser()-----------");
	}

	@Override
	public String getUserName(int id) {
		System.out.println("------------getUserName()-----------");
		return null;
	}

}

    3.编写客户端类Client.java对UserManager实现进行测试。
package proxy;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		UserManager manager = new UserManagerImpl();
		manager.addUser(1, "zhangsan", 24);
	}

}
     输出结果为------------addUser()-----------

    现在,想在所有UserManager函数调用之前,先对用户信息进行安全性检查,就需要在所有的函数执行前添加安全性检查,如代码UserManagerImpl.java所示。
package proxy;

public class UserManagerImpl implements UserManager {

	@Override
	public void addUser(int id, String name, int age) {
		security();
		System.out.println("------------addUser()-----------");
	}

	@Override
	public void deleteUser(int id) {
		security();
		System.out.println("------------deleteUser()-----------");
	}

	@Override
	public String getUserName(int id) {
		security();
		System.out.println("------------getUserName()-----------");
		return null;
	}
	
	private void security(){
		System.out.println("------------security()--------------");
	}
}
    这样实现会打破程序设计的封装性,如果需要添加功能就需要需改程序的源代码,因此这里就需要使用代理的思想。
    增加一个代理,代理类可以控制原对象,所以在调用原对象之前就可以进行安全性检查。

    添加代理类UserManagerImplProxy.java
package proxy;

public class UserManagerImplProxy implements UserManager {

	private UserManager manager;
	
	public UserManagerImplProxy(UserManager manager){
		this.manager = manager;
	}
	@Override
	public void addUser(int id, String name, int age) {
		security();
		this.manager.addUser(id, name, age);
	}

	@Override
	public void deleteUser(int id) {
		security();
		this.manager.deleteUser(id);
	}

	@Override
	public String getUserName(int id) {
		security();
		return this.manager.getUserName(id);
	}
	
	private void security(){
		System.out.println("------------security()--------------");
	}
}

    将实际对象通过构造函数传递给代理类,在调用实际对象方法前添加对安全性的检查security()方法,通过使用代理将需要添加的功能从UserMangerImpl类中分离出来
修改后的Client.java代码如下。
package proxy;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		UserManager manager = new UserManagerImpl();
//		manager.addUser(1, "zhangsan", 24);
		UserManager manager = new UserManagerImplProxy(new UserManagerImpl());
		manager.addUser(1, "zhangsan", 24);
	}

}
    程序输出为------------security()--------------
      ------------addUser()-----------

    代理模式:在实际开发当中使用频率非常高的一种设计模式。
    定义:为其他对象提供一种代理机制以控制这个对象的访问。
    代理对象要与目标对象的接口一致。

    以上是简单代理的实现方式,在实际使用中,使用最多的是动态代理。代理对象会在运行期生成。

    编写安全性检查的处理方法类SecurityHandler.java
package proxy;

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

public class SecurityHandler implements InvocationHandler {

	private Object targerObject;
	
	public Object newProxyObject(Object targetObject){
		this.targerObject = targetObject;
		Object object = Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
<span style="white-space:pre">							</span>targetObject.getClass().getInterfaces(),
							this);
		return object;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		security();
		Object result = null;
		try{
			result = method.invoke(this.targerObject, args);
		}catch(Exception e){
			e.printStackTrace();
		}
		return result;
	}

	private void security(){
		System.out.println("------------security()--------------");
	}
}
    下面对动态代理的实现进行说明
    1.需要实现InvocationHandler接口,并实现这个接口当中的invoke方法。当调用代理对象的方法的时会自动调用invoke方法,所以可以将安全性检查的方法放到invoke方法中,这样在调用目标对象的方法前就会调用security()方法了。
    2.在SecurityHandler方法中声明了一个Object类型的实例变量,用来存储目标对象。
    3.编写newProxyObject方法,这个方法将目标对象赋值给实例变量targerObject来保存目标对象。
    4.调用Proxy的newProxyInstance函数来创建一个代理对象,该函数有3个参数,分别是ClassLoader,接口数组(Class<?>[])以及一个InvocationHandler。
      JVM在加载类的时候就是通过调用ClassLoader的loadClass()方法来加载类的,而第二个参数是一个接口数组,这就是说明被代理的类需要实现某个接口,当然也可以不实现接口,使用CGLIB技术,这个技术不在本文讨论范围内。第三个参数是一个InvocationHandler,这里置为this即可。
    
    修改Client.java
package proxy;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		UserManager manager = new UserManagerImpl();
//		manager.addUser(1, "zhangsan", 24);
//		UserManager manager = new UserManagerImplProxy(new UserManagerImpl());
//		manager.addUser(1, "zhangsan", 24);
		
		SecurityHandler proxy = new SecurityHandler();
<span style="white-space:pre">		</span>UserManager manager = (UserManager)proxy.newProxyObject(new UserManagerImpl());
<span style="white-space:pre">		</span>manager.addUser(1, "zhangsan", 24);
	}

}

    程序输出为------------security()--------------
             ------------addUser()-----------
    创建一个SecurityHandler对象,然后创建一个目标对象,调用newProxyObject函数获得这个对象的一个代理对象,再调用代理对象的方法,这样即可实现动态代理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值