黑马程序员_JAVA动态代理技术学习笔记

来源:互联网 发布:逃犯 熊孩子 知乎 编辑:程序博客网 时间:2024/05/23 12:04
------- android培训、java培训、期待与您交流! ----------


1、代理的作用

1)要为已存在的,多个具有相同接口的目标类的各个方法增加一些系统功能。

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

3)如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中使用目标类、还是代理类,这样以后很容易切换。


2、AOP(aspect oriented program)

面向方面的编程:交叉业务的编程问题。eg:安全、事物、日志。

用代理技术实现。


3、动态代理技术

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

JVM生成的动态类必须实现一个或多个接口。所以,JVM生成的动态类只能作用具有相同接口的目标类的代理。

CGLIB库可以动态生成一个类的子类,一个类的子类也可用作该类的代理。所以没有实现接口的类,可以使用CGLIB库(CGLIB为第三方库)

代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果,还可以在如下四个位置加上系统功能代码:

1)调用目标方法之前;

2)调用目标方法之后;

3)调用目标方法前后;

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


4、获取动态创建的字节码

java.lang.reflect.Proxy

静态方法:getProxyClass(ClassLoader loader, Class<?>... interfaces)

以上方法用于获取动态类。

参数一:表示类加载器(一般与第二个参数的类加载器相同)

参数二:相关类的加载器

eg:

Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);


5、分类写字节码(该实现方式实现的代理,属于硬编码方式,仅供学习,不建议使用)

Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);//获取动态字节码Constructor constructor = clazzProxy.getConstructor(InvocationHandler.class);//获取字节码构造器Collection proxy1 = (Collection) constructor.newInstance(new MyInvocationHandler());//获取动态代理实例,这里入参MyInvocationHandler实现了接口InvocationHandlerproxy1.add("1");//实例操作proxy1.clear();//实例操作


6、匿名内部类写法(代理硬编码方式,仅供学习,不建议使用)

Collection proxy2 = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{Collection.class},new InvocationHandler(){ArrayList tartget = new ArrayList();//<-操作实例,实际上,就是指这个目标对象的代理,目标对象是接口的一个实例。@Overridepublic Object invoke(Object proxy, Method method,//<-对invoke()的实现,代理实例的每次方法调用都用到invoke()方法Object[] args) throws Throwable {long start = System.currentTimeMillis();Object returnVal = method.invoke(tartget, args);//<-这礼调用用户实际调用的方法long end = System.currentTimeMillis();System.out.println(method.getName()+" Run time:"+ (end-start));//<-在代理中实现执行时间的统计return returnVal;//<-返回用户实际调用的方法的返回值}});proxy2.add("1");//<-方法调用proxy2.add("2");//<-方法调用proxy2.add("3");//<-方法调用System.out.println(proxy2.size());//<-方法调用


7、对于Object继承的方法,只有hashCode()、equals()、toString()交给目标实现,其它的,代理自己实现。


8、代理的通用方案

1)、比较通用的框架代理示例,eg:

private static Object getProxy(final Object target,final Advice advice) {Object proxy = Proxy.newProxyInstance(//创建代理实例target.getClass().getClassLoader(), //1、定义类加载器target.getClass().getInterfaces(),//2、定义接口new InvocationHandler(){//3、定义InvocationHandler@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {advice.beforeMethod(method);//执行advice中的执行前操作。Object returnVal = method.invoke(target, args);//执行目标方法。advice.afterMethod(method);//执行advice中的执行后操作。return returnVal;//然会目标方法的返回值。}});return proxy;//<--这边感觉有点问题}


2)比较通用的代理调用方法示例,eg:
Object target = new ArrayList();Object proxy = getProxy(target,new MyAdvice());//这边advice可以和Spring中的框架类比


3)Advice的写法参考示例,(这边advice可以和Spring中的框架类比),eg:

public interface Advice {//目标方法运行前操作void beforeMethod(Method method);//目标方法运行后操作void afterMethod(Method method);}


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


0 0
原创粉丝点击