代理设计模式

1、反射

通过反射加载类的构造器并新建对象

package ref;

import java.lang.reflect.InvocationTargetException;

public class ReflectServiceImpl {
    private String name;

    public void sayHello(){
        System.out.println("hello "+name);
    }

    public ReflectServiceImpl(String  name) {
        this.name = name;
    }

    public static void main(String[] args) {
        ReflectServiceImpl object = null;
        try {
            object = (ReflectServiceImpl) Class.forName("ref.ReflectServiceImpl").getConstructor(String.class).newInstance("aa");
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        System.out.println(object.getClass().getName());
        object.sayHello();
    }
}

通过反射执行方法,这种执行是在先使用new关键字创建了对象的情况下,也可以使用反射创建对象然后反射执行方法

        ReflectServiceImpl target = new ReflectServiceImpl();
        Method method = ReflectServiceImpl.class.getMethod("sayHello", String.class);
        method.invoke(target,"张三"); 

其实就是把上面的两种结合起来

       ReflectServiceImpl target = (ReflectServiceImpl)Class.forName("ref.ReflectServiceImpl").newInstance();
        Method method = ReflectServiceImpl.class.getMethod("sayHello", String.class);
        method.invoke(target,"张三");

 

 

2、动态代理

  所谓代理模式就是在不改变方法源码的情况下对原方法进行增强,允许用户在运行期间创建基于接口的代理去增强接口代码。该技术涉及到反射中的两个类:Proxy InvocationHandler。实现invocationHandler接口的类负责把接口的逻辑和要增强的逻辑组装起来,Proxy通过新建代理对象的方式来执行InvocationHandler的组合逻辑。

  实现动态代理首先要有一个接口,以及该接口的一个实现类作为被代理的对象。

package daili;

public class Actor_01 implements Actor {

    @Override
    public void act(float money) {
        System.out.println("开始普通表演 拿到:"+money);
    }

    @Override
    public void dangerAct(float money) {
        System.out.println("开始危险表演 拿到:"+money);

    }
}
package daili;

public interface Actor {
    void act(float money);
    void dangerAct(float money);
}

  然后实现InvocationHandler接口的类作为代理对象,代理对象调用被代理的对象的相关方法,以及织入横切逻辑。所以代理对象里一定要有被代理对象的引用,实现这种引用既可以通过属性的方式来实现,也可以用个匿名内部类调用外部类属性来实现,但是后者要求该属性必须是final,这或多或少有一点侵入的意思,所以这里采用了直接实现InnovationHandler方式。

  invoke方法中,调用method.invoke是执行被代理的对象的方法,而在method.invoke前后就是可以随意织入的方法。

public class ActorHandler implements InvocationHandler {
    private Actor actor;

    public void setActor(Actor actor) {
        this.actor = actor;
    }

    public ActorHandler(Actor actor) {
        this.actor = actor;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("我是代理公司");
        float money= (float)args[0];
        Object result = null;
        if (money>100){
            System.out.println("演员可以演");
            result = method.invoke(actor, args);
        }else {
            System.out.println("钱太少 我不让我的演员演");
        }
        return result;
    }
}

  最后一步是调用Proxy的static方法newProxyInstance来调用增强后的方法。

public class Client {
    public static void main(String[] args) {
        Actor_01 actor_01 = new Actor_01();
        Actor proxyInstance = (Actor)Proxy.newProxyInstance(actor_01.getClass().getClassLoader(), actor_01.getClass().getInterfaces(), new ActorHandler(actor_01));
        proxyInstance.act(100f);
        proxyInstance.act(500f);
    }
}

 

posted @ 2019-04-08 11:45  AshOfTime  阅读(145)  评论(0编辑  收藏  举报