美文网首页
《Java编程思想》读书笔记 第十四章 02 反射

《Java编程思想》读书笔记 第十四章 02 反射

作者: goule1994 | 来源:发表于2017-07-14 15:10 被阅读28次

    《Java编程思想》读书笔记 第十四章 02 反射

    反射机制

    反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为反射

    反射机制的功能及实现

    • 在运行时判断任意一个对象所属的类
    • 在运行时构造任意一个类的对象
    • 在运行时判断任意一个类所具有的成员变量和方法
    • 在运行时调用任意一个对象的方法
    • 生成动态代理

    将反射机制应用于工厂模式

    interface Fruit {
        public abstract void eat();
    }
    class Apple implements Fruit {
        public void eat() { System.out.println("Apple"); }
    }
    class Orange implements Fruit {
        public void eat() { System.out.println("Orange"); }
    }
    class Factory {
        public static <T> T getInstance(String className) {
        T obj = null;
        try {
            obj = (T) Class.forName(className).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
        }
    }
    public class TestReflect4 {
        public static void main(String[] args) throws Exception {
        Fruit fruit = Factory.getInstance("Apple");
        if (fruit != null)
            fruit.eat();
        }
    }
    

    动态代理

    代理是一本基本的设计模式;代理通常充当着中间人的角色

    ==静态代理:==

    interface Interface {
        void doSomething();
        void somethingElse(String arg);
    }
    
    class RealObject implements Interface {
        public void doSomething() {
            System.out.println("doSomething");
        }
        public void somethingElse(String arg) {
        System.out.println("somethingElse " + arg);
        }
    }
    
    class SimpleProxy implements Interface {
        private Interface profixed;
        public SimpleProxy(Interface profixed) {
        this.profixed = profixed;
        }
        public void doSomething() {
        System.out.println("SimpleProxy doSomething");
        profixed.doSomething();
        }
        public void somethingElse(String arg) {
        System.out.println("SimpleProxy somethingElse " + arg);
        profixed.somethingElse(arg);
        }
    }
    
    public class SimpleProxyDemo {
        public static void consumer(Interface iface) {
        iface.doSomething();
        iface.somethingElse("bonobo");
        }
        public static void main(String[] args) {
        consumer(new RealObject());//直接操作RealObject对象
            //通过SimpleProxy代理类对象间接操作RealObject对象
        consumer(new SimpleProxy(new RealObject()));
        }
    }
    
    

    ==jdk动态代理:==
    http://www.cnblogs.com/xiaoluo501395377/p/3383130.html

    Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    proxy:  指代我们所代理的那个真实对象
    method: 指代的是我们所要调用真实对象的某个方法的Method对象
    args:  指代的是调用真实对象某个方法时接受的参数
    
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    loader:   一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载//TODO
    interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,
               如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),
               这样我就能调用这组接口中的方法了
    h:       一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
    举例:
    //首先我们定义了一个Subject类型的接口,为其声明了两个方法:
    public interface Subject
    {
        public void rent();
        
        public void hello(String str);
    }
    //接着,定义了一个类来实现这个接口,这个类就是我们的真实对象,RealSubject类:
    public class RealSubject implements Subject
    {
        @Override
        public void rent()
        {
            System.out.println("本身自己的方法");
        }
        
        @Override
        public void hello(String str)
        {
            System.out.println("hello: " + str);
        }
    }
    //下一步,我们就要定义一个动态代理类了,前面说个,每一个动态代理类都必须要实现 InvocationHandler 这个接口,因此我们这个动态代理类也不例外:
    public class DynamicProxy implements InvocationHandler
    {
        //这个就是我们要代理的真实对象
        private Object subject;
    
        //构造方法,给我们要代理的真实对象赋初值
        public DynamicProxy(Object subject)
        {
            this.subject = subject;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //在代理真实对象前我们可以添加一些自己的操作
            System.out.println("我来代理你,带你飞");
            System.out.println("**** proxy: " + proxy.getClass().getName()
                    + ", method: " + method + ", args: " + args);
            //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
            method.invoke(subject, args);
            //在代理真实对象后我们也可以添加一些自己的操作
            System.out.println("代理完成,安全降落");
            return null;
        }
    
        /**
         * <T>向下转型
         * @param <T>
         * @return
         */
        public <T> T getProxy() {
            return (T) Proxy.newProxyInstance(
                    subject.getClass().getClassLoader(),
                    subject.getClass().getInterfaces(),
                    this
            );
        }
    }
    //最后,来看看我们的Client类:
    public class Client
    {
        public static void main(String[] args)
        {
            //    我们要代理的真实对象
            Subject realSubject = new RealSubject();
    
            //    我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
            DynamicProxy handler = new DynamicProxy(realSubject);
    
            /*
             * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
             * 参数1:ClassLoader
             * 参数2:该实现类的所有接口
             * 参数3:动态代理对象。
             */
            SubjectService subject = handler.getProxy();
            subject.rent();
            subject.hello("啦啦啦!!!");
        }
    }
    
    

    ==cligb动态代理:==
    https://my.oschina.net/huangyong/blog/159788

    public class CGLibProxy implements MethodInterceptor {
    
        public <T> T getProxy(Class<T> cls) {
            return (T) Enhancer.create(cls, this);
        }
    
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("我来代理你,带你飞");
            System.out.println("**** proxy: " + proxy.getClass().getName()
                    + ", method: " + method + ", args: " + args);
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("代理完成,安全降落");
            return result;
        }
    }
    单利模式:
    public class CGLibProxy implements MethodInterceptor {
    
        private static CGLibProxy instance = new CGLibProxy();
    
        //限制外界不能再去new
        private CGLibProxy() {
        }
    
        public static CGLibProxy getInstance() {
            return instance;
        }
    
        public <T> T getProxy(Class<T> cls) {
            return (T) Enhancer.create(cls, this);
        }
    
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            System.out.println("我来代理你,带你飞");
            System.out.println("**** proxy: " + proxy.getClass().getName()
                    + ", method: " + method + ", args: " + args);
            Object result = proxy.invokeSuper(obj, args);
            System.out.println("代理完成,安全降落");
            return result;
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            //jdk动态代理
            SubjectServiceImpl subjectService = new SubjectServiceImpl();
            DynamicProxy handler = new DynamicProxy(subjectService);
            SubjectService subject = handler.getProxy();
            subject.rent();
            subject.hello("啦啦啦!!!");
    
            //Cglib动态代理
            CGLibProxy cgLibProxy = new CGLibProxy();
            SubjectServiceImpl subjectProxy = cgLibProxy.getProxy(SubjectServiceImpl.class);
            subjectProxy.rent();
            subjectProxy.hello("啦啦啦");
            //单利模式cglib动态代理
            SubjectServiceImpl subjectProxy = CGLibProxy.getInstance().getProxy(SubjectServiceImpl.class);
            subjectProxy.rent();
            subjectProxy.hello("啦啦啦");
        }
    }
    
    

    我一向都是以追求完美而著称,2 行代码返回代理对象,我觉得还是有些多余,我不想总是去 new 这个 CGLibProxy 对象,最好 new 一次,以后随时拿随时用。于是我想到了“单例模式”

    相关文章

      网友评论

          本文标题:《Java编程思想》读书笔记 第十四章 02 反射

          本文链接:https://www.haomeiwen.com/subject/ejtohxtx.html