黑马程序员——高新技术(代理、动态代理)

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

代理
代理原理:

1、编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。

2、如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置,从而确定使用的是目标类还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。

代理架构图:


实例如下:

interface Person{//目标类和代理类需要实现的相同接口
	public void study();
}
class TargetTest implements Person{//目标类
	public void study(){
		System.out.println("学习");
	}
}
class ProxyTest implements Person{//代理类
	private Person person;
	ProxyTest(Person person){
		this.person=person;
	}
	public void study(){
		System.out.println("在教室");//通过代理类添加一些功能
		person.study();//调用目标类的方法
		System.out.println("学习累了,休息一下");//通过代理类添加一些功能
	}
}
class TestDemo{//客户端
	public static void main(String[] args){
		TargetTest tt=new TargetTest();
		ProxyTest pt=new ProxyTest(tt);
		pt.study();
	}
}
备注:通过以上代码可以看出,客户端实际要调用的是TargetTest中的study方法,但通过ProxyTest代理TargetTest,调用ProxyTest中的study方法,不但能得到目标类中的方法,而且还能添加一些功能,达到功能增强的目的。

面向方面的编程:全称Aspect oriented program,简称AOPAOP的目标就是要使交叉业务模块化,可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。

如下举例说明:



动态代理类JVM可以在运行期间动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。

1、JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
2、CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
3、代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标和返回结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
(1)在调用目标方法之前;
(2)在调用目标方法之后;
(3)在调用目标方法前后;

(4)在处理目标方法异常的catch块中。

动态代理类综合实例(动态代理小型框架):

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.LinkedList;
public class ProxyTest {
	public static void main(String[] args) {
		LinkedList arr=new LinkedList();
		MyAdvice ma=new MyAdvice();//此处为加入的系统代码对象
		Collection al=(Collection)getProxy(arr,ma);
		al.add("455");	
	}
	/*此方法为动态获得一目标类的代理类,此种写法是犹如一种小型的框架*/
	private static Object getProxy(final Object target,final Advice advice){//获得动态代理
		Object proxy1=Proxy.newProxyInstance(//通过Proxy中的方法获得动态代理对象
				target.getClass().getClassLoader(),//此参数为目标类的加载器
				target.getClass().getInterfaces(), //此参数为目标类所实现的接口
				new InvocationHandler(){
			public Object invoke(Object proxy, Method method,//复写InvocationHandler中的方法
					Object[] args) throws Throwable {
				advice.beginTime();//在调用目标方法之前加功能代码
				Object retVal=method.invoke(target, args);//调用目标的方法
				advice.overTime();//在调用目标方法之后加功能代码
				return retVal;
			}
		});
		return proxy1;
	}
}
功能代码接口,提高拓展性:

public interface Advice {
	public void beginTime();
	public void overTime();
}
实现功能代码接口,定义子类:

public class MyAdvice implements Advice {
	public void beginTime() {
		System.out.println("开始了");
	}
	public void overTime() {
		System.out.println("结束了");
	}
}
说明:通过以上代码可以知道,通过java虚拟机可以比较容易的获得很多目标类的动态代理,大大提高了代码的复用性。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值