------- android培训、java培训、期待与您交流! ----------
代理的概念和作用
为实现相同接口的目标类的各个方法添加一些系统功能,如工作日志、性能测试、权限控制等。
面向方面的编程(AOP):系统存在交叉业务、一个交叉业务要切入到系统中的一个面。
上图中的安全、事物、日志管理就是交叉事物。
动态代理
如果为每个类编写一个代理类,工作量巨大。所以jvm可以 动态的生成代理类。
JVM可以在运行期间动态的生成类的字节码,这种动态类往往被用作代理类,即动态代理类。
JVM动态生成代理类的条件:
1)Jvm生成动态类的必须实现一个或者多个接口,所以,jvm生成的动态类只能用作具有相同接口的目标类的代理类
2)CGLIB库可以动态的生成一个类的子类,这个子类可以用做该类的代理。
代理类添加功能的位置:
1、目标方法之前。
2、目标方法之后。
3、目标方法的前后。
4、可以在try catch块中
定义一个简单的动态代理类:
先自定义一个接口。
然后再定义一个实现了 Myinterface 接口的类package com.heima.proxy; //自定以一个接口 public interface Myinterface { //接口中的一个方法。 public void sayHello(String str); }
通过Proxy产生一个 MyClassDemo 的代理类:package com.heima.proxy; //定义一个实现了Myinterface接口的类 public class MyClassDemo implements Myinterface { //实现sayHello方法 @Override public void sayHello(String str) { System.out.println(str); } }
package com.heima.proxy; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyDemo { /** * @param args */ public static void main(String[] args) throws Exception { // 通过Proxy得到一个基于Myinterface接口的代理类的class。 Class clazz=Proxy.getProxyClass(Myinterface.class.getClassLoader(), Myinterface.class); //通过反射得到代理类的构造方法 Constructor constr =clazz.getConstructor(InvocationHandler.class); //构造一个代理类的实例 Myinterface proxy = (Myinterface) constr.newInstance( new InvocationHandler(){ //创建目标类 MyClassDemo my = new MyClassDemo(); @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在执行目标类的目标方法之前调用的代码 System.out.println("调用之前的代码"); //执行目标方法并且获得返回值 Object obj= method.invoke(my, args); //在执行目标类的目标方法之后调用的代码 System.out.println("调用之后的代码"); return obj; } } ); //通过代理类调用目标方法 proxy.sayHello("hello world"); } }
执行后的结果 :
调用之前的代码
hello world
调用之后的代码
然后将产生代理的方法做成通用的方法。
package com.heima.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; public class ProxyDemo { /** * @param args */ public static void main(String[] args) throws Exception { ArrayList<String > list = new ArrayList<String >(); Advice advice = new Advice(); //获得代理类 Collection<String> proxy = (Collection) getMyProxy(list,advice); //验证是否调用了目标类的方法 System.out.println(list.size()); //通过代理类调用目标方法 proxy.add("adb"); //验证是否调用了目标类的方法 System.out.println(list.size()); } public static Object getMyProxy(Object target,Advice advice) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { final Object mytarget =target; final Advice madvice =advice; //检查目标类、目标类的接口、advice类是否为空 if(target ==null||target.getClass().getInterfaces()==null||advice==null) { throw new RuntimeException("目标或者建议类为空"); } Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader() , target.getClass().getInterfaces() , new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //执行目标方法之前执行的操作 madvice.doBefore(); //执行目标方法 Object result =method.invoke(mytarget, args); //执行方法之后执行的操作 madvice.doAfter(); return result; } }); return proxy; } }
执行结果:
0
执行方法之前
执行方法之后
1