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

2017-07-14  本文已影响28人  goule1994

《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 一次,以后随时拿随时用。于是我想到了“单例模式”

上一篇下一篇

猜你喜欢

热点阅读