java 反射 动态代理

    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方法的调用

}

  

posted on 2010-07-24 11:23 nod0620 阅读(806) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 
<2024年12月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

导航

统计

常用链接

留言簿

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜