一、类加载器:
在虚拟机运行时将class文件加载到硬盘和内存中的工作就是由类加载器来完成的;JAVA虚拟中可以安装多个类加载器,系统默认三个主要类加载器:
BootStrap,ExtClassLoader,AppLoader;每个类加载器负责加载特定位置的类;类加载器也是Java类,所以其他类加载器也要被类加载器所加载,所以有一个类加载器必须不是类,这个就是BootStrap;
自定义类加载器------------用户指定的目录下的类
2、自定义类加载器:
①用户自己定义的类加载器必须继承ClassLoader类
②覆盖findClass()方法(模板设计模式,若是覆盖了loadClass方法,那么用户就必须自己定义向上传递加载请求等一系列功能的语句)1、程序中的代理:
①要为已存在的多个具有相同接口的目标类的各个方法增加一些系统功能,例如异常处理,日志,计算方法的运行时间,事务管理等等;
②编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码;③如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置到底是使用目标类还是代理类
3、动态代理技术:
①JVM可以在运行期间动态的生成出类的字节码,这种动态的生成的往往被用作代理类,即动态代理类;
②JVM动态的生成的类必须实现一个或多个接口,所以动态生成的类之恩你更用作实现了相同接口的类的代理类;1、动态生成一个类的字节码:
Proxy.getProxyClass(类加载器,需要实现的接口字节码)
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);package cn.ittest.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
public class ProxyDemo
{
public static void main(String[] args) throws Exception, NoSuchMethodException
{
//获取Collection的动态代理
Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
Constructor[] cs = clazzProxy.getConstructors(); //获取动态代理类的所有构造方法
for(Constructor c : cs) //遍历构造方法
{
String name = c.getName(); //获取构造方法的名字
StringBuffer sb = new StringBuffer(name);
sb.append("(");
Class[] clazzParams = c.getParameterTypes(); //获取构造方法的类型参数
for(Class s : clazzParams)
{
sb.append(s).append(",");
}
if(c!=null)
sb.deleteCharAt(sb.length()-1);
sb.append(")");
System.out.println("构造方法:");
System.out.println(sb.toString()); //打印次构造方法
System.out.println("所有方法:");
}
//获取Collection的动态代理
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
Method[] methods = clazzProxy1.getMethods(); //获取动态代理类的所有方法
for(Method m : methods) //遍历方法
{
String name = m.getName(); //获取方法的名字
StringBuffer sb1 = new StringBuffer(name);
sb1.append("(");
Class[] clazzParames = m.getParameterTypes(); //获取方法的类型参数
for(Class s : clazzParames)
{
sb1.append(s).append(",");
}
if(m!=null)
sb1.deleteCharAt(sb1.length()-1);
sb1.append(")");
System.out.println(sb1.toString()); //打印次所有方法
}
}
//获取指定类的动态代理
public static Object getProxy(final Object object,final Mainboard mainboard)
{
Object relVal = Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
new InvocationHandler()
{
public Object invoke(Object arg0, Method method,Object[] arg) throws Throwable
{
mainboard.opend(); //在调用代理类的每个方法时,加上自定义代码
Object relVal = method.invoke(object,arg);
mainboard.close();
return relVal;
}
}
);
return relVal;
}
四、
了解InvocationHandler对象invoke方法的作用之后就知道如何添加代理功能,在具体实现中一般是将需要运行的代码做成一个对象传递到匿名的InvocationHandler实现类中去
通常的方法是让匿名InvocationHandler实现类去访问外面方法中的目标类实例对象的final类型的引用变量