RTTI处理类时必须在编译器知道类型,那么在运行时的动态链接部分就没有办法了,这时候需要另外的一个功能:反射
反射设计的类有Class以及reflect类库里面的Filed,Method等等。这些类对象由jvm在运行时进行创建,用于表示动态链接类里面对应的成员。
RTTI和反射最大的区别是:RTTI在编译期打开和检查class文件,反射则在运行时打开和检查class文件,class文件在编译期可能还不存在
在反射的更高一层是动态代理,代理是一种设计模式,他用代理对象代替实际对象,并在前后插入必要的操作,代理对象和实际对象实现相同的接口。
动态代理是比静态代理更好玩的思想,动态的创建代理并动态处理对所代理方法的调用
动态代理的步骤:
1.自己实现InvocationHandler接口,可以在构造器当中传入你需要的被代理的对象。
2.通过Proxy指定类加载器以及一组需要被代理的类的接口来创建动态代理类
3.通过反射机制得到动态代理类的构造函数,参数类型是InvocationHandler
4.创建动态代理实例,参数是第一步的InvocationHandler的实现类对象
动态代理产生的类是继承了Proxy类,实现了被代理类的接口,可以自由的转型鸟。
查看源代码:
public static Class<?> getProxyClass(ClassLoader loader,
Class<?> interfaces)
throws IllegalArgumentException
{
//超过65535虚拟机规范不允许
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
Class proxyClass = null;
String[] interfaceNames = new String[interfaces.length];
Set interfaceSet = new HashSet();
for (int i = 0; i < interfaces.length; i++) {
//检查每个接口是不是能用类加载器加载进来
String interfaceName = interfaces[i].getName();
Class interfaceClass = null;
try {
interfaceClass = Class.forName(interfaceName, false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != interfaces[i]) {
throw new IllegalArgumentException(
interfaces[i] + " is not visible from class loader");
}
/*
* Verify that the Class object actually represents an
* interface.
*/
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
*/
if (interfaceSet.contains(interfaceClass)) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
interfaceSet.add(interfaceClass);
interfaceNames[i] = interfaceName;
}
/*
* Using string representations of the proxy interfaces as
* keys in the proxy class cache (instead of their Class
* objects) is sufficient because we require the proxy
* interfaces to be resolvable by name through the supplied
* class loader, and it has the advantage that using a string
* representation of a class makes for an implicit weak
* reference to the class.
*/
Object key = Arrays.asList(interfaceNames);
/*
* Find or create the proxy class cache for the class loader.
*/
Map cache;
synchronized (loaderToCache) {
//缓存的使用,类加载器为key
cache = (Map) loaderToCache.get(loader);
if (cache == null) {
cache = new HashMap();
loaderToCache.put(loader, cache);
}
/*
* This mapping will remain valid for the duration of this
* method, without further synchronization, because the mapping
* will only be removed if the class loader becomes unreachable.
*/
}
/*
* Look up the list of interfaces in the proxy class cache using
* the key. This lookup will result in one of three possible
* kinds of values:
* null, if there is currently no proxy class for the list of
* interfaces in the class loader,
* the pendingGenerationMarker object, if a proxy class for the
* list of interfaces is currently being generated,
* or a weak reference to a Class object, if a proxy class for
* the list of interfaces has already been generated.
*/
synchronized (cache) {
/*
* Note that we need not worry about reaping the cache for
* entries with cleared weak references because if a proxy class
* has been garbage collected, its class loader will have been
* garbage collected as well, so the entire cache will be reaped
* from the loaderToCache map.
*/
do {
//key为一组接口的list,如果有值的话,直接返回,这个cache是为了性能
Object value = cache.get(key);
if (value instanceof Reference) {
proxyClass = (Class) ((Reference) value).get();
}
if (proxyClass != null) {
// proxy class already generated: return it
return proxyClass;
} else if (value == pendingGenerationMarker) {
//这里说明正有另外一个线程在创建对象
// proxy class being generated: wait for it
try {
cache.wait();
} catch (InterruptedException e) {
/*
* The class generation that we are waiting for should
* take a small, bounded time, so we can safely ignore
* thread interrupts here.
*/
}
continue;
} else {
/*
* No proxy class for this list of interfaces has been
* generated or is being generated, so we will go and
* generate it now. Mark it as pending generation.
*/
cache.put(key, pendingGenerationMarker);
break;
}
} while (true);
}
try {
String proxyPkg = null; // package to define proxy class in
/*
* 检测非公共接口,如果是分散到不同的包中,那么抛出异常,因为如果产生
* 代理类,有访问不了的可能性
*/
for (int i = 0; i < interfaces.length; i++) {
int flags = interfaces[i].getModifiers();
if (!Modifier.isPublic(flags)) {
String name = interfaces[i].getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) { // if no non-public proxy interfaces,
proxyPkg = ""; // use the unnamed package
}
{
/*
* Choose a name for the proxy class to generate.
*/
long num;
synchronized (nextUniqueNumberLock) {
num = nextUniqueNumber++;
}
//代理的名称为 包名+“$proxy”+N
String proxyName = proxyPkg + proxyClassNamePrefix + num;
/*
* Verify that the class loader hasn't already
* defined a class with the chosen name.
*/
/*
* Generate the specified proxy class.
*/
//这一步读入二进制文件,然后产生代理类
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces);
try {
proxyClass = defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
// add to set of all generated proxy classes, for isProxyClass
proxyClasses.put(proxyClass, null);
} finally {
/*
* We must clean up the "pending generation" state of the proxy
* class cache entry somehow. If a proxy class was successfully
* generated, store it in the cache (with a weak reference);
* otherwise, remove the reserved entry. In all cases, notify
* all waiters on reserved entries in this cache.
*/
synchronized (cache) {
//如果proxyClass不为空则加入缓存,否则删除这个key
if (proxyClass != null) {
cache.put(key, new WeakReference(proxyClass));
} else {
cache.remove(key);
}
cache.notifyAll();
}
}
return proxyClass;
}
基本上所有的精华在
ProxyGenerator里面,这个下回分解
在看看我们产生的代理类$ProxyN,形式应该如下:
public final class ProxySubject extends Proxy
implements Subject{
//继承Proxy ,实现接口
ProxySubject(InvocationHandler handler){
}
/*
* 这个里面有object的hashcode,equals,toString
* 方法的重写,我认为是为了这些方法的行为准则
* 是跟着被代理类一起走的
* 这个里面也有接口方法的调用,基本上调用的函
* 数是:
*/
super.h.invoke(this, m3, null);
//也就是传入handler的invoke方法的调用
}