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

来源:互联网 发布:手机图片排版软件 编辑:程序博客网 时间:2024/05/29 03:14

------- 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虚拟机可以比较容易的获得很多目标类的动态代理,大大提高了代码的复用性。