zoukankan      html  css  js  c++  java
  • proxy 简化版本

    public interface People {
        public String eat(String param);
    }
    
    public class Jack implements People {
        @Override
        public String eat(String param) {
            System.out.println("=========Jack老师喜欢吃东=======");
            return "=========Jack老师喜欢吃东=======";
        }
    }
    
    public class Advice implements InvocationHandler1 {
        
        People people;//接口,传进来实例
        
        public Advice(People people) {
            this.people = people;
        }
        
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //前置增强
            before();
            //被代理方
            Object value = method.invoke(people,args);
            //后置增强
            after();
            return value;
        }
    
        private void before() {
            System.out.println("===========jack吃饭之前�?要洗�?==========");
        }
    
        private void after() {
            System.out.println("===========jack吃完饭要洗碗=============");
        }
    }
    
    public class MyTest {
        public static void main(String[] args) {
            People proxyObject = (People) Proxy1.newProxyInstance(MyTest.class.getClassLoader(),
                    new Class<?>[] { People.class }, new Advice(new Jack())); // 获取代理,MyTest.class.getClassLoader()是类加载器,
            //new Advice是对实现类new Jack()的增强,People.class是接口,在吃饭之前之后要洗手,
    
            proxyObject.eat("chi");// proxyObject是在内存的代理对象,对象名字$Proxy数字,
      
            //proxyObject = com.zhuguang.jack.aop.jdkProxy.Jack@5e5792a0,里面的h = com.zhuguang.jack.aop.jdkProxy.Advice@26653222

         // $Proxy0/1 extends Proxy1 implements People,Proxy里面有一个属性InvocationHandler h; // proxyObject.eat("chi")调用的是h.invoke(Object proxy, Method method, Object[] // args), // h.invoke()方法调到advice.invoke(), } }
    public class Proxy1 implements java.io.Serializable {
    
        private static final long serialVersionUID = -2222568056686623797L;
        private static final Class<?>[] constructorParams = { InvocationHandler1.class };
        private static final WeakCache1<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache1<>( new ProxyClassFactory());
        protected InvocationHandler1 h;
        private Proxy1() {}
    
        protected Proxy1(InvocationHandler1 h) {
            Objects.requireNonNull(h);
            this.h = h;
        }
    
        //一个利用给定的类加载器和接口类数组生成,定义并返回代理类对象的工厂方法。代理类生成工厂。
        private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> {
            private static final String proxyClassNamePrefix = "$Proxy1";
            private static final AtomicLong nextUniqueNumber = new AtomicLong();
            @Override
            public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
                String proxyPkg = null; // 代理类的包名
                int accessFlags = Modifier.PUBLIC | Modifier.FINAL;//生成代理类的访问标志, 默认是public final的
                //验证所有非公共代理接口都在同一个包中
                for (Class<?> intf : interfaces) {
                    int flags = intf.getModifiers();//获取接口的访问标志
                    //如果接口的访问标志不是public, 那么生成代理类的包名和接口包名相同
                    if (!Modifier.isPublic(flags)) {
                        accessFlags = Modifier.FINAL;//生成的代理类的访问标志设置为final
                        String name = intf.getName();//获取接口全限定名, 例如:java.util.Collection
                        int n = name.lastIndexOf('.');
                        String pkg = ((n == -1) ? "" : name.substring(0, n + 1));//剪裁后得到包名:java.util
                        if (proxyPkg == null) {//生成的代理类的包名和接口包名是一样的
                            proxyPkg = pkg;
                        } else if (!pkg.equals(proxyPkg)) {//代理类如果实现不同包的接口, 并且接口都不是public的, 那么就会在这里报错
                            throw new IllegalArgumentException("non-public interfaces from different packages");
                        }
                    }
                }
                //如果接口访问标志都是public的话, 那生成的代理类都放到默认的包下:com.sun.proxy
                if (proxyPkg == null) {
                    proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
                }
                long num = nextUniqueNumber.getAndIncrement();
                String proxyName = proxyPkg + proxyClassNamePrefix + num;
                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);//com.sun.proxy.$Proxy10,[interface proxy.People],
                try {// 返回代理类对象,根据二进制文件生成相应的Class实例。
                    return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
                } catch (Exception  e) {
                    System.out.println(e.toString());
                }
                return null;
            }
        }
    
        public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler1 h) throws IllegalArgumentException {
            final Class<?>[] intfs = interfaces.clone();//[interface proxy.People], 
            Class<?> cl =  proxyClassCache.get(loader, intfs);//先走WeakCache的get(),再通过Factory的get方法,最后通过ProxyClassFactory的apply()获取代理类的Class对象。
            try {
                // 从代理类对象中查找参数为InvocationHandler的构造器,获取参数类型是InvocationHandler.class的代理类构造器
                final Constructor<?> cons = cl.getConstructor(constructorParams);
                final InvocationHandler1 ih = h;
                // 检测构造器是否是Public修饰,如果不是则强行转换为可以访问的。
                if (!Modifier.isPublic(cl.getModifiers())) {
                    AccessController.doPrivileged(new PrivilegedAction<Void>() {
                        public Void run() {
                            cons.setAccessible(true);
                            return null;
                        }
                    });
                }
                // 通过反射,将h作为参数,实例化代理类,返回代理类实例。2.利用反射技术实例化代理类,并返回实例化对象。传入InvocationHandler实例去
                //构造一个代理类的实例,所有代理类都继承自Proxy, 因此这里会调用Proxy的构造器将InvocationHandler引用传入,
                return cons.newInstance(new Object[] { h });
            } catch (Exception e) {
                throw new InternalError(e.toString(), e);
            } 
        }
    
        private static native Class<?> defineClass0(ClassLoader loader, String name, byte[] b, int off, int len);
    }
    final class WeakCache1<K, P, V> {
        private final BiFunction<K, P, V> valueFactory;
    
        public WeakCache1(BiFunction<K, P, V> valueFactory) {//构造方法,,,
            this.valueFactory = Objects.requireNonNull(valueFactory);//new ProxyClassFactory()
        }
    
        public V get(K key, P parameter) { 
            Supplier<V> supplier = null; 
            Factory factory = null;
    
            while (true) {
                if (supplier != null) {
                    V value = supplier.get();
                    if (value != null) {
                        return value; 
                    }
                }
                if (factory == null) {
                    factory = new Factory(key, parameter );
                }
                if (supplier == null) {
                    if (supplier == null) {
                        supplier = factory;
                    }
                } 
            }
        }
    
        private final class Factory implements Supplier<V> {
            private final K key;
            private final P parameter;
    
            Factory(K key, P parameter) {
                this.key = key;
                this.parameter = parameter;
            }
    
            @Override
            public synchronized V get() {  
                V value = null;
                // valueFactory就是WeakCache的valueFactory属性,因为Factory是WeakCache的内部类,所以可以直接访问WeakCache的valueFactory属性
                value = valueFactory.apply(key, parameter);
                return value;
            }
        }
    
    }
  • 相关阅读:
    A. SwapSort
    D. A Shade of Moonlight
    利用DataSet更改数据,将更改保存到数据库中
    接口设计与数据同步解决方案小结
    SQL 判断 ‘表,存储过程,函数 ...’ 已是否存在
    SQL Server系统表sysobjects介绍与使用
    【转】SQL Server 2008 事件探查器(SQL SERVER Profiler)
    SQL 常用语句
    网页开发 组件
    中文版的jqGrid实例大全
  • 原文地址:https://www.cnblogs.com/yaowen/p/11750311.html
Copyright © 2011-2022 走看看