黑马程序员--Java基础--15动态代理

本文深入探讨了Java动态代理的原理与应用,通过代码示例展示了如何利用动态代理实现功能扩展与AOP编程,提供了从概念理解到实践操作的全面指南。

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

动态代理

利用代理可以在运行时创建一个实现了一组给定接口的新类,这种功能只有在编译时无法确定需要实现哪个接口时才有必要使用。


JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
    JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。

代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
1.在调用目标方法之前
2.在调用目标方法之后
3.在调用目标方法前后
4.在处理目标方法异常的catch块中

 

和动态代理有关的有两个类 
1.interface InvocationHandler 
Object invoke(Object proxy, Method method, Object[] args) 

在代理实例上处理方法调用并返回结果。

2.class Proxy 
真正表示动态代理的类,提供两个静态方法
Class<?> getProxyClass(ClassLoader loader, Class<?>[] interface) 
用来产生代理类,参数要提供interface数组,它会生成这些interface虚拟实现, 
用来冒充真实的对象。 

Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 
产生代理对象,多了InvocationHandler参数(只是InvocationHandler接口的实现类), 
它与代理对象关联,当请求分发到代理对象后,会自动执行h.invoke(...)方法

 

代理类具用以下属性:

1.代理类是公共的、最终的,而不是抽象的。

2.未指定代理类的非限定名称。但是,以字符串 "$Proxy" 开头的类名空间应该为代理类保留。

3.代理类扩展 java.lang.reflect.Proxy

4.代理类会按同一顺序准确地实现其创建时指定的接口。

5.如果代理类实现了非公共接口,那么它将在与该接口相同的包中定义。否则,代理类的包也是未指定的。注意,包密封将不阻止代理类在运行时在特定包中的成功定义,也不会阻止相同类加载器和带有特定签名的包所定义的类。

6.由于代理类将实现所有在其创建时指定的接口,所以对其 Class 对象调用 getInterfaces 将返回一个包含相同接口列表的数组(按其创建时指定的顺序),对其 Class 对象调用 getMethods 将返回一个包括这些接口中所有方法的 Method 对象的数组,并且调用 getMethod 将会在代理接口中找到期望的一些方法。

7.如果 Proxy.isProxyClass 方法传递代理类(由 Proxy.getProxyClass 返回的类,或由 Proxy.newProxyInstance 返回的对象的类),则该方法返回 true,否则返回 false

8.代理类的 java.security.ProtectionDomain 与由引导类加载器(如 java.lang.Object)加载的系统类相同,原因是代理类的代码由受信任的系统代码生成。此保护域通常被授予 java.security.AllPermission

9.每个代理类都有一个可以带一个参数(接口 InvocationHandler 的实现)的公共构造方法,用于设置代理实例的调用处理程序。并非必须使用反射 API 才能访问公共构造方法,通过调用 Proxy.newInstance 方法(将调用 Proxy.getProxyClass 的操作和调用带有调用处理程序的构造方法结合在一起)也可以创建代理实例。

 

示例:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

/*
 *动态代理 
 */
public class AOPTest {
	public static void main(String[] args) {
		// 返回代理类的 java.lang.Class对象,并向其提供类加载器和接口数组
		Class clazzProxy = Proxy.getProxyClass(Collection.class
				.getClassLoader(), Collection.class);
		System.out.println(clazzProxy.getName());
		// 获取全部构造方法
		Constructor[] constructors = clazzProxy.getConstructors();
		for (Constructor constructor : constructors) {
			String name = constructor.getName();
			// StringBuffer是线程安全的,StringBuilder是线程不安全的。
			// StringBuilder在单线程的时候使用,StringBuffer则是在多线程的时候使用。
			// 因此StringBuilder比StringBuffer效率高一些。
			StringBuilder sBuilder = new StringBuilder(name);
			sBuilder.append("(");
			// 返回此 Constructor对象所表示的方法的形参类型
			Class[] clazzParams = constructor.getParameterTypes();
			for (Class clazzParam : clazzParams) {
				sBuilder.append(clazzParam.getName()).append(",");
			}
			if (clazzParams != null && clazzParams.length != 0) {
				// 删除最后的,
				sBuilder.deleteCharAt(sBuilder.length() - 1);
			}
			sBuilder.append(")");
			System.out.println(sBuilder);
		}

		// 获取全部方法名及参数
		System.out.println("--------begin methods list-------");
		Method[] methods = clazzProxy.getMethods();
		for (Method method : methods) {
			String name = method.getName();
			StringBuilder sBuilder = new StringBuilder(name);
			sBuilder.append("(");
			Class[] clazzParams = method.getParameterTypes();
			for (Class clazzParam : clazzParams) {
				sBuilder.append(clazzParam.getName()).append(",");
			}
			if (clazzParams != null && clazzParams.length != 0) {
				sBuilder.deleteCharAt(sBuilder.length() - 1);
			}
			sBuilder.append(")");
			System.out.println(sBuilder);
		}

		// 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序
		Collection proxy = (Collection) Proxy.newProxyInstance(Collection.class
				.getClassLoader(), new Class[] { Collection.class },
				new InvocationHandler() {
					ArrayList target = new ArrayList();

					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						long beginTime = System.currentTimeMillis();
						Object retVal = method.invoke(target, args);
						long endTime = System.currentTimeMillis();
						System.out.println(method.getName()
								+ " running out of " + (endTime - beginTime));
						return retVal;
					}
				});
		proxy.add("zxx");
		proxy.add("lhm");
		proxy.add("bxd");
		System.out.println(proxy.size());
	}
}

输出:

com.sun.proxy.$Proxy0

com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler)

--------begin methods list-------

add(java.lang.Object)

equals(java.lang.Object)

toString()

hashCode()

clear()

contains(java.lang.Object)

isEmpty()

addAll(java.util.Collection)

iterator()

size()

toArray([Ljava.lang.Object;)

toArray()

remove(java.lang.Object)

containsAll(java.util.Collection)

removeAll(java.util.Collection)

retainAll(java.util.Collection)

isProxyClass(java.lang.Class)

getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)

newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)

getInvocationHandler(java.lang.Object)

wait(long)

wait()

wait(long,int)

getClass()

notify()

notifyAll()

add running out of 317

add running out of 0

add running out of 0

size running out of 0

3


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


内容概要:本文围绕“基于分布式模型预测控制的多个固定翼无人机一致性控制”展开,利用Matlab代码实现相关算法的仿真,旨在通过分布式控制策略实现多架固定翼无人机在复杂动态环境中的协同飞行与一致性控制。研究结合模型预测控制(MPC)方法,构建适用于多无人机系统的分布式优化框架,重点解决了通信受限、信息延迟及无中心化指挥条件下的协同稳定性问题。内容涵盖固定翼无人机的动力学建模、分布式MPC优化求解机制、一致性协议设计、通信拓扑结构分析以及仿真验证全过程,确保多机系统在保持队形一致的同时完成协同任务。; 适合人群:具备自动控制理论、无人机系统建模或多智能体协同控制基础,从事智能无人系统、集群控制、自动化与机器人等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于多无人机协同编队飞行、集群侦察、分布式任务执行等实际工程场景;②为分布式MPC算法在多智能体系统中的一致性控制提供可复现的Matlab仿真案例,推动先进控制理论向工程实践转化;③服务于科研论文复现、算法验证、控制系统课程设计与毕业课题参考。; 阅读建议:建议读者结合文中提供的Matlab代码逐模块运行与调试,重点关注分布式MPC在不同通信拓扑下对一致性收敛性能的影响,并可通过调整预测时域、权重矩阵与噪声参数等方式深化对算法鲁棒性与适应性的理解。
内容概要:本文提出了一种基于变分模态分解(VMD)、麻雀搜索算法(SSA)优化与长短期记忆网络(LSTM)相结合的光伏功率预测模型(VMD-SSA-LSTM),旨在提升光伏发电预测的精度与鲁棒性。该方法首先利用VMD对原始非平稳光伏功率序列进行自适应分解,获得一系列具有更稳定特征的本征模态分量(IMFs),有效降低数据复杂性与噪声干扰;随后引入麻雀搜索算法(SSA)对LSTM网络的关键超参数(如学习率、隐层节点数等)进行全局寻优,克服传统试凑法效率低、易陷入局部最优的问题,显著提升模型收敛速度与泛化能力;最后,构建多个LSTM子模型分别预测各模态分量,并将结果重构得到最终的光伏功率预测值。该混合模型充分融合了VMD在信号预处理中的优异分解性能、SSA在参数优化中的高效搜索能力以及LSTM在捕捉时间序列长期依赖关系上的强大建模优势,实现了对复杂气象因素影响下光伏出力波动的高精度拟合与预测。; 适合人群:具备一定电力系统、新能源发电或时间序列预测基础知识,熟悉MATLAB编程环境,从事光伏功率预测、智能电网调度、可再生能源集成、负荷预测等领域研究的科研人员、工程技术人员及高校研究生。; 使用场景及目标:①应用于光伏电站的短期与超短期功率预测,为电网安全调度、电力市场交易、储能系统配置及需求侧响应提供精准数据支撑;②解决传统单一预测模型(如ARIMA、BPNN、单一LSTM)在处理非平稳、强波动性光伏数据时存在的精度不足、稳定性差等问题;③为风电、负荷等其他非平稳时序预测问题提供一种有效的“分解-优化-预测”混合建模范式与技术实现路径。; 阅读建议:建议读者结合文中提供的完整MATLAB代码,深入理解VMD信号分解、SSA优化算法流程及LSTM网络构建的每一个技术环节,通过实际历史数据进行模型复现与对比实验(如与VMD-LSTM、SSA-LSTM等模型比较),掌握参数调优技巧与模型性能评估方法,从而真正掌握该先进混合预测模型的核心思想与应用精髓。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值