JAVA的动态代理



JAVA的动态代理模式,理解上要分开,一个是纯代理模式,另一个是动态反射。
例子定义了两个接口,飞行接口,扣篮接口,投篮接口,其中乔丹实现了这三个接口,科比只实现了投篮与扣篮两个接口。
动态代理,一句简单的话来讲,就是:
Proxy类为我们建立出一个实体类的副本a,该副本a只对外声明了实现类实现的所有接口中的方法,且副本中保存了一个invocationHandler的实现类b。
此时的a就是一个代理类,当用户拿a去调用接口的方法时(即代理模式),JVM会将该副本类a及用户要调用的方法名还有参数交由b,通过反射机制实现【动态】调用



/**
 * 篮球运动员 投篮 的接口
 * */
public interface PlayerShoot {
	public void shoot();
}

/**
 * 运动员飞行接口
 * */
public interface PlayerFly {
	public void fly();
}

/**
 * 篮球运动员 扣篮 的接口
 * */
public interface PlayerDunk {
	public void dunk();
}

/**
 * 迈克尔乔丹  实现了投篮和扣篮这两个接口
 * */
public class MichaelJordan implements PlayerShoot, PlayerDunk,PlayerFly{

	@Override
	public void dunk() {
		System.out.println("Michael Jordan Dunk!!!WOW!!!");
	}

	@Override
	public void shoot() {
		System.out.println("Michael Jordan Shoot!!!Got it!!!");
	}

	@Override
	public void fly() {
		System.out.println("Look at that,mj is flying.....");
	}
}

/**
 * 科比类,同样实现了扣篮与投篮两个接口
 * */
public class Kobe implements PlayerShoot, PlayerDunk {

	@Override
	public void dunk() {
		System.out.println("Kobe Dunk!!!WOW!!!Not in!!");
	}

	@Override
	public void shoot() {
		System.out.println("Kobe Shoot!!!Fuck hit the rim!!!");
	}

}

/**
 * 这个类不是代理对象,而是代理对象中方法的调用渠道
 * */
public class GameHandle implements InvocationHandler {
	
	private Object player;
	
	public GameHandle(Object player){
		this.player = player;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		
		method.invoke(this.player, args);
		return null;
	}

	public Object getPlayer() {
		return player;
	}

	public void setPlayer(Object player) {
		this.player = player;
	}
}

public class GameStart {
	/**
	 * JAVA的动态代理小结
	 * 
	 * 1, 明确真实对象所具备的方法,即声明真实对象要实现的接口,起名曰 ability_interface
	 * 
	 * 2, 明确真实对象所属类的方法的具体实现,即真实对象类要实现ability_interface中的所有方法,起名曰 ability_class
	 * 
	 * 3,使用JVM的机制,实现接口InvocationHandler,实现类中必须实现invoke方法,起名曰inner_reflection
	 * 
	 * 4,创建代理对象,使用Proxy.newProxyInstance方法,依次传递arg1,arg2,arg3,依次对应ability_class的classLoader,ability_interface中定义的方法,inner_reflection
	 *    此时,创建出的代理对象起名曰ProxyObject,简单理解起来,ProxyObject就是ability_class的一个副本,只不过,对外只公开ability_interface中定义的方法
	 *    
	 *    注意:在创建ProxyObject的时候,JVM会将inner_reflection通过构造函数传递给ProxyObject,由此,ProxyObject就知道了由谁来通过反射机制调用其内的方法
	 *    
	 * 5,此时,拿着ProxyObject就可以调用ability_interface中的方法了,参数由用户指定,而该方法的调用,则是由JVM将其传递给与ProxyObject中保存的inner_reflection
	 *    这里是通过反射机制来完成的,即将ProxyObject和其内要调用的方法名及用户指定的参数交由inner_reflection的invoke方法来调用
	 *    
	 *    至此,就实现了通过JAVA的反射机制,针对不同真实对象的代理模式
	 * 
	 * */
	public static void main(String[] args) {
		
		/**
		 * 这里有两个真实对象需要被代理,一个是乔丹,一个是科比
		 * */
		MichaelJordan mj = new MichaelJordan();
		Kobe kb = new Kobe();
		
		Class<?> mjClass = mj.getClass();
		Class<?> kbClass = kb.getClass();
		
		/**
		 * 创建代理对象方法的调用渠道
		 * */
		InvocationHandler bc = new GameHandle(kb);
		
		/**
		 * 创建真实对象 科比 的代理对象
		 * */
		Object actionkb = Proxy.newProxyInstance(kbClass.getClassLoader(), kbClass.getInterfaces(), bc);
		/**
		 * 拿着科比的代理对象去调用科比已“具备的能力”,即其已实现的接口
		 * */
		((PlayerDunk)actionkb).dunk();
		((PlayerShoot)actionkb).shoot();
		
		/**
		 * 现在需要代理 乔丹了,去创建出乔丹的代理对象
		 * */
		((GameHandle)bc).setPlayer(mj);
		Object actionmj = Proxy.newProxyInstance(mjClass.getClassLoader(), mjClass.getInterfaces(), bc);
		/**
		 * 此时拿乔丹的代理对象去调用乔丹所具备的能力
		 * */
		((PlayerDunk)actionmj).dunk();
		((PlayerShoot)actionmj).shoot();
		((PlayerFly)actionmj).fly();
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值