-------
android培训
、
java培训
、期待与您交流! ----------
什么是代理:要为已存在的多个具有相同接口的目标类的方法增加一些系统功能。比如:事物处理,异常处理,日志等。
也就是业务交叉。面向切面编程AOP(Aspect Oriented program)
什么是动态代理:JVM可以再运行期间动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
两中实现方式:
JVM生成动态类必须实现一个或多个接口,所以jvm生成的动态类只能用作具有相同接口的目标类的代理。
什么是代理:要为已存在的多个具有相同接口的目标类的方法增加一些系统功能。比如:事物处理,异常处理,日志等。
也就是业务交叉。面向切面编程AOP(Aspect Oriented program)
什么是动态代理:JVM可以再运行期间动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
两中实现方式:
JVM生成动态类必须实现一个或多个接口,所以jvm生成的动态类只能用作具有相同接口的目标类的代理。
怎么让一个没有实现接口的类生成动态代理类呢?可以使用CGLIB库。他可以动态的生成一个类的子类,一个类的子类也可以用作该类代理类。
动态代理工作原理图:
代码实现:分析JVM生成动态类,以及获取生成动态类的方法信息列表
package Proxy;
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 ProxyDemo {
/**
* @分析JVM生成动态类,以及获取生成动态类的方法信息列表
*/
public static void main(String[] args) throws Exception{
//通过反射获取jvm生成动态的字节码文件
//参数说明: 第一个参数classLoader:一般使用使用接口的类加载器,第二个参数:该动态类需要实现的接口
Class clazzProxy1= Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy1.getName());
//获取构造方法
Constructor[] constructors=clazzProxy1.getConstructors();
for(Constructor constructor: constructors){
System.out.println(constructor);
//这个打印出public $Proxy0(java.lang.reflect.InvocationHandler) 。说明只有一个构造方法。
}
System.out.println("begin new instance-------");
Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
Collection proxy1=(Collection) constructor.newInstance(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
});
System.out.println(proxy1);
// proxy1.size(); size()方法有返回值。报空指针错误
System.out.println("第二种创建动态实例对象方法:");
Collection proxy2=(Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler() {
ArrayList traget=new ArrayList();
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long beginTime=System.currentTimeMillis();
Object retVal=method.invoke(traget, args);
long endTime=System.currentTimeMillis()-beginTime;
System.out.println(method.getName()+"耗时"+(endTime-beginTime));
return retVal;
}
});
proxy2.add("zd");
proxy2.add("lx");
proxy2.add("wcb");
System.out.println(proxy2.size());
}
}
面向切面实现,把代理类封装使用,可以插入日志信息等:
package Proxy;
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 ProxyDemo2 {
public static void main(String[] args) {
Collection traget=new ArrayList();
Collection proxy2 = (Collection) getProxy(traget,new AdvicceService());
proxy2.add("zd");
proxy2.add("lx");
proxy2.add("wcb");
System.out.println("---------"+proxy2.size());
}
/**
* 此方法可以一直使用,动态代理类
* @param traget
* @param advice
* @return proxy2
*/
private static Object getProxy(final Object traget,final Advice advice) {
Object proxy2= Proxy.newProxyInstance(
traget.getClass().getClassLoader(), //用什么接口就用它的类加载器
traget.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
advice.beforMethod(method);
Object retVal=method.invoke(traget, args);
advice.afterMethod(method);
return retVal;
}
});
return proxy2;
}
}
接口:
package Proxy;
import java.lang.reflect.Method;
public interface Advice {
void beforMethod(Method method);
void afterMethod(Method method);
}
接口实现类:
package Proxy;
import java.lang.reflect.Method;
public class AdvicceService implements Advice {
private long beginTime=0;
@Override
public void beforMethod(Method method) {
beginTime=System.currentTimeMillis();
}
@Override
public void afterMethod(Method method) {
long endTime=System.currentTimeMillis()-beginTime;
System.out.println(method.getName()+"耗时"+(endTime-beginTime));
}
}
-------
android培训
、
java培训
、期待与您交流! ----------