代理模式之动态代理

在上一篇博客https://blog.youkuaiyun.com/weixin_39453325/article/details/84201400中我们详细讲解了静态代理模式,很显然静态代理有如下的缺点。

静态代理的缺点:因为代理对象需要与目标对象实现一样的接口,一般一个目标对象类需要对应一个代理类,所以会有很多代理类,类太多,不易管理。同时,一旦接口增加方法,目标对象与代理对象都要维护。

解决方法:使用动态代理,其实动态代理与静态代理的思想是一样的,动态代理与静态代理的区别是,动态代理不用我们为每一个接口去编写特定的代理类,在运行时,动态的在内存中产生代理类。

动态代理

动态代理是一种较为高级的代理模式,它的典型应用就是 Spring AOP。

在传统的代理模式中,客户端通过 Proxy 调用 RealSubject 类的 request() 方法,同时还在代理类中封装了其他方法(如 preRequest() 和 postRequest() ),可以处理一些其他问题。如果按照这种方法使用代理模式,那么真实主题角色必须是事先已经存在的,并将其作为代理对象的内部成员属性,如果一个真实主题角色必须对应一个代理主题角色,这将导致系统中类的个数急剧增加,因此需要想办法减少系统中类的个数,此外,如何在事先不知道真实主题角色的情况下使用代理主题角色,这都是动态代理需要解决的问题。

Java 动态代理实现相关类位于 java.lang.reflect 包,主要涉及两个类:

-- InvocationHandler 接口。它是代理实例的调用处理程序实现的接口,该接口中定义了如下方法:

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

invoke() 方法中的第一个参数 proxy 表示代理类,第二个参数 method 表示需要代理的方法,第三个参数 args 表示代理方法的参数数组。

-- Proxy 类。该类即为动态代理类,该类最常用的方法为:

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

newProxyInstance() 方法用于根据传入的接口类型 interfaces 返回一个动态创建的代理类的实例,方法中第一个参数 loader 表示代理类的类加载器,第二个参数 interfaces 表示代理类实现的接口列表(与真实主题类的接口列表一致),第三个参数 h 表示所指派的调用处理程序类。

代理模式实例与解析

本处的实例来自上篇静态代理的实例一https://blog.youkuaiyun.com/weixin_39453325/article/details/84201400,学者可参考比较来学习。

接口类:

/**
 * 接口方法
 * @author 14517
 *
 */
public interface UserManager {
	public void addUser(String username,String password);
	public void deleteUser(int id);
	public void modifyUser(int id,String username,String password);
	public String findUserById(int id);
}

目标类 :

/**
 * 实现 UserManager 接口
 * @author 14517
 *
 */
public class UserManagerImpl implements UserManager {

	@Override
	public void addUser(String username, String password) {
		System.out.println("---UserManagerImpl addUser()---");
	}

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

	@Override
	public void modifyUser(int id, String username, String password) {
		System.out.println("---UserManagerImpl modifyUser()---");
	}

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

}

代理类(动态代理,代理类没有实现和目标对象一样的接口,而是通过 JavaAPI 在内存中为我们动态创建一个代理对象) :

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * jdk 动态代理,只要实现 InvocationHandler 接口,即可代理所有接口
 * @author 14517
 *
 */
public class DynamicProxyHandler implements InvocationHandler {
	/**
	 * 目标对象
	 */
	private Object targetObject;
	/**
	 * @param object
	 * @return 代理对象
	 */
	public Object newProxy(Object object) {
		this.targetObject=object;
		return Proxy.newProxyInstance(object.getClass().getClassLoader(), 
				object.getClass().getInterfaces(), 
				this);
	}
	/**
	 * @param proxy 代理类
	 * @param method 需要代理的方法
	 * @param args 代理方法的参数组
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		checkBefore();
		Object ret=method.invoke(this.targetObject,args);
		checkAfter();
		return ret;
	}
	/**
	 * 方法执行之前调用
	 */
	public void checkBefore() {
		System.out.println("---Before---");
	}
	/**
	 * 方法执行之后调用
	 */
	public void checkAfter() {
		System.out.println("---After---");
	}
}

测试类: 

/**
 * 动态代理测试
 * @author 14517
 *
 */
public class DynamicProxyTest {
	
	public static void main(String[] args) {
		DynamicProxyHandler handler=new DynamicProxyHandler();
		UserManager um=(UserManager) handler.newProxy(new UserManagerImpl());
		um.addUser("DynamicProxyHandler", " ");
		um.deleteUser(1);
		um.modifyUser(1, "DynamicProxyHandler", " ");
		um.findUserById(1);
	}
}

执行程序,输出结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值