黑马程序员_代理类知识总结

本文深入探讨了Java动态代理的概念、作用、应用场景、工作原理及常见问题,结合实际代码示例,详细解释了如何利用动态代理增强代码功能、简化系统维护流程,并通过实践案例展示了动态代理在Java和Android开发中的应用。文章还涵盖了JVM生成动态代理类的两种方法,以及在实际开发中遇到的问题与解决方案。

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

------------------------------------------------android培训java培训期待与您交流!-----------------------------------------------

代理的作用

为了便于在目标类的方法之前和之后加上一些系统功能而存在
(如:异常处理、日志、计算方法的运行时间、事务管理),当调用
代理类方法的时候它会调用目标类里面的相同方法

代理的运用场景

比方说客户端想要调用调用有记录日志的功能的相关方法那么就在
配置文件里面配置代理类,当不需要日志功能的时候则配置目标类,
这样,增加系统功能很方便,以后运行一段时间后,又想去掉系统功能也
很方便AOP:(切面编程)就运用了代理,其要领就是在要调用的方法功能之
前或之后添加其他功能方法

JVM生成的动态类必须实现一个或多个接口

JVM生成的动态类只能用具有相同接口目标类的代理,如果该类没有接口
可以使用CGLIB库可以动态生成一个类的动态代理子类

以被代理对象转发被InvocationHandler.invoke()处理的方法有

①类中继承下来的除了hashCode、equals 或 toString,

② 代理对象需要实现的接口方法;然而其他的方法都有它们自己的实现如getClass();

动态代理的工作原理

客户端调用代理,代理对象的构造方法接受一个handler对象,客户端调用代理的
各个方法,各个方法会把调用请求转发给通过构造方法传递进来的那个handler
对象handler对象再通过method(客户端调用的那个方法)调用目标类的相应方法


JVM生成动态代理类的两种方法

 ①第一种方式

//1.获得代理类的Class类
	Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
	//2.从class类中得到构造器类
	Constructor constructor = clazzProxy1.getConstructor(InvocationHandler.class);
	//3.通过构造器类对象实例化一个代理类
    Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){

		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			return null;
		}
		
	});System.out.println(proxy3);
proxy3.clear();
proxy3.size();


 
  ②第二种方式
//target为目标代理类
	Object proxy3 = Proxy.newProxyInstance(
			target.getClass().getClassLoader(),
			target.getClass().getInterfaces(),
			new InvocationHandler(){				//参数分别是:代理的对象,代理调用的方法,调用方法时传递的参数
				public Object invoke(Object proxy, Method method, Object[] args)
						throws Throwable {
					return null;						
					
				}
			}
			);

遇到的问题
在6点的①中System.out.println(proxy3);打印结果为null
proxy3.clear();
proxy3.size();而这句执行的时候报错
①解释以上原因

打印proxy3的时候由于invoke返回的是null,而System.out.println(proxy3);相当于执行的是System.out.println(proxy3.toString);前面第四点我们就说toString可以被invoke()处理所以返回结果是null那么就打印出null字符串

②proxy3.size()这句出错的原因

是因为代理类是这样的

Class Proxy$ {
int size() {
//因为size()方法需要返回的值是int型而返回的值却是null所以报错
return handler.invoke(Object proxy, Method method, Object[] args);
}

为了更加的面向对象和更好的编码常常把目标类和系统功能类抽取出来

/**
	 * @param target传递目标的类
	 * @param advice传递系统功能
	 * @return动态生成的代理类
	 */
	private static Object getProxy(final Object target, final Advice advice)
	{
		Object proxy3 = Proxy.newProxyInstance(target.getClass().getClassLoader(),
		target.getClass().getInterfaces(), new InvocationHandler()
		{

			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
			{
				advice.beforeMethod(method);
				Object retVal = method.invoke(target, args);
				advice.afterMethod(method);
				return retVal;

			}
		});
		return proxy3;
	}

零散知识点

每一个class要加载到内存来必须要有一个类加载器
StringBuilder不考虑多线程其效率比StringBuffer高
可变参数只能用于最后


-----------------------------------------android培训java培训、java学习型技术博客、期待与您交流! --------------------------


详情请查看:http://edu.csdn.net/heima








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值