黑马程序员--java高新技术--动态代理

来源:互联网 发布:全球中文地图导航软件 编辑:程序博客网 时间:2024/05/29 15:09

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

1.什么是代理?

一种用于转发请求,进行特殊处理的机制。“动态”指的是运行期。

2.为什么使用动态代理?

可以对请求进行任何处理

3.使用它有什么好处?

4.哪些地方需要动态代理?

不允许直接访问某些类,对访问要做特殊处理。




AOP面向方面的编程:

系统中存在许多交叉业务,一个交叉业务就是要切入到系统的一个方面。

同样的动作会在不同的模块中,这些动作就是模块的交叉业务。


可以把这些交叉业务都当做一个切面:



交叉业务的编程问题即为面向方面的编程(Aspect oriented program ,简称AOP),AOP的目标就是要使交叉业务模块化。可以采

用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的,如下所示:



使用代理技术可以解决aop的核心技术。

jvm可以在运行期动态生产出一个类,这种动态生成的类往往北用作代理,既动态代理。

动态类必须实现一个或多个接口。

CGLIB可以生成没有实现接口和类的动态代理。


package cn.jhc.day3;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 ProxyTest {/** * @param args */public static void main(String[] args) throws Exception{// TODO Auto-generated method stub//Proxy.getProxyClass(类加载器, 接口)Class classProxy1 =         Proxy.getProxyClass(Collection.class.getClassLoader(),        Collection.class);//System.out.println(classProxy1.getName());System.out.println("----begin constructors list ----");/* * $Proxy0() * $Proxy0(InvocationHandler,int) * *///获取类的所有构造方法。Constructor[] constructors = classProxy1.getConstructors();for (Constructor constructor : constructors) {//得到构造方法名String name = constructor.getName();StringBuilder sBuilder = new StringBuilder(name);//性能比buffer高sBuilder.append('(');//得到构造方法的参数Class[] classParams = constructor.getParameterTypes();for (Class classParam : classParams) {sBuilder.append(classParam.getName()).append(',');}if(classParams.length != 0 && classParams != null)sBuilder.deleteCharAt(sBuilder.length()-1);sBuilder.append(')');System.out.println(sBuilder.toString());}System.out.println("----begin methods list ----");/* * $Proxy0() * $Proxy0(InvocationHandler,int) * *///得到所有方法Method[] methods = classProxy1.getMethods();for (Method method : methods) {//得到方法名String name = method.getName();StringBuilder sBuilder = new StringBuilder(name);//性能比buffer高sBuilder.append('(');//得到方法的参数Class[] classParams = method.getParameterTypes();for (Class classParam : classParams) {sBuilder.append(classParam.getName()).append(',');}if(classParams.length != 0 && classParams != null)sBuilder.deleteCharAt(sBuilder.length()-1);sBuilder.append(')');System.out.println(sBuilder.toString());}System.out.println("----begin create instance object ----");//classProxy1.newInstance();//得到构造方法Constructor constructor = classProxy1.getConstructor(InvocationHandler.class);//InvocationHandler是一个接口//class MyInvocationHandler1 implements InvocationHandler{////@Override//public Object invoke(Object proxy, Method method, Object[] args)//throws Throwable {//// TODO Auto-generated method stub//return null;//}////}//Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHandler1());//System.out.println(proxy1);//proxy1.clear();////proxy1.size();////创建代理对象,创建匿名内部接口Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){//实现接口的invoke方法。@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stubreturn null;}});final ArrayList target = new ArrayList();Collection proxy3 = (Collection)getProxy(target,new MyAdvice());proxy3.add("zxx");proxy3.add("bxd");proxy3.add("bad");System.out.println(proxy3.size());}private static Object getProxy(final Object target,final Advice advice) {Object proxy3 = Proxy.newProxyInstance(target.getClass().getClassLoader(),//new Class[]{Collection.class},target.getClass().getInterfaces(),new InvocationHandler(){@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {// TODO Auto-generated method stub//long beginTime = System.currentTimeMillis();//Object retVal = method.invoke(target, args);//long endTime = System.currentTimeMillis();//System.out.println(method.getName() + " running time of " + (endTime - beginTime));//return retVal;//在目标前实现自己的方法advice.beforeMethod(method);Object retVal = method.invoke(target, args);//在目标后实现自己的方法advice.afterMethod(method);return retVal;}});return proxy3;}}


总结一下需要注意的地方:

目标方法要求返回的值类型与代理类返回的值类型应当保持一致;

newProxyInstance()方法可以得到一个动态代理类,它需要接受3个参数

public static Object newProxyInstance(ClassLoader loader, 

Class<?>[] interfaces, 

InvocationHandler h)

Loader:一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载

Interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了

h一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

InvocationHandler中需要实现的invoke()方法接受三个参数

invoke(Object proxy, Method method,Object[] args)

proxy: 指代我们所代理的那个真实对象

method: 指代的是我们所要调用真实对象的某个方法的Method对象

args: 指代的是调用真实对象某个方法时接受的参数

这个invoke方法要用到这些参数的原因是:代理类要去找目标类的方法并调用,然后返回。


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

0 0
原创粉丝点击