动态代理

1静态代理

首先先看不使用代理

public class Man implements Action {
    private String name;

    public Man(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void sayHello() {
        System.out.println(this.name + " say hello");

    }

    @Override
    public void eat(String food) {
        System.out.println("eat " + food);
        
    }

}
男人
public interface Action {
    void sayHello();

    void eat(String food);
}
Action
public class Man implements Action {
    private String name;

    public Man(String name) {
        super();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void sayHello() {
        System.out.println(this.name + " say hello");

    }

}
public interface Action {
    void sayHello()
    public static void main(String[] args) {
        Man man = new Man("jj");
        man.sayHello();
    }
测试类

上面是一个不使用静态代理的普通代码,但当我们想对sayHello方法增强其的功能时,比如增加一个openMouth行为时就不得不修改sayhello的代码逻辑,这不符合设计原则,所以我们可以使用代理模式进行代码修改。

public class StaticProxy implements Action {
    private Man man;

    public StaticProxy(Man man) {
        super();
        this.man = man;
    }

    @Override
    public void sayHello() {
        // TODO Auto-generated method stub
        openMouth();
        man.sayHello();
    }

    private void openMouth() {
        System.out.println(man.getName() + "open mouth");
    }

}
静态代理
public static void main(String[] args) {
        Man man = new Man("jj");
        StaticProxy sp = new StaticProxy(man);
        sp.sayHello();
    }
测试类

这样我们通过代理对象实现man对象的sayhello方法的增强后功能。这样的好处是,假如是Man每个方法都要增加日志功能,不可能在每个方法中加入log方法,我们可以在代理类的实现方法中调用Man的对应方法,后面再增加log逻辑。实现解耦合。

我们可以总结一下静态代理 1.代理类和被代理类都要实现相同的接口(代理类要对被代理类进行功能增强的,不实现相同的接口,代理类就不知道增强什么功能) 2.代理类需要持有被代理类实例对象(功能增强是代理类和被代理类共同协作的结果)3.代理类进行实际的行为

2.jdk动态代理

public class DynamicProxyHandller implements InvocationHandler {
    private Object proxyed;

    public Object getProxyed() {
        return this.proxyed;
    }

    public void setProxyed(Object proxyed) {
        this.proxyed = proxyed;
    }

    // 获取代理实例
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(proxyed.getClass().getClassLoader(), proxyed.getClass().getInterfaces(), this);
    }

    public DynamicProxyHandller(Object proxyed) {
        super();
        this.proxyed = proxyed;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        dosomeBefore();
        method.invoke(proxyed, args);
        return null;
    }

    public void dosomeBefore() throws Exception {
        Field field = proxyed.getClass().getDeclaredField("name");
        field.setAccessible(true);
        System.out.println((String) field.get(proxyed) + " dosomeBefore");

    }

}
动态代理handler
public static void main(String[] args) {

        Action man = new Man("jj");
        DynamicProxyHandller dp = new DynamicProxyHandller(man);
        Action ac = (Action) dp.getProxyInstance();
        ac.sayHello();
        ac.eat("apple");

    }
测试类
jj dosomeBefore
jj say hello
jj dosomeBefore
jj eat apple

从测试类中看出,我们先实例一个包含被代理类对象的动态代理handler(实现了InvocationHandler接口),然后通过handler实例一个代理对象,再通过代理对象去做相应的行为。这样整个动态代理就这样完成。

那么这样的好处又是什么?

首先静态代理和动态代理的区别很明显,静态代理有实际的代理类还需实现接口,动态代理只有一个handler,通过handler去实例一个代理对象。

然后假如Action接口里面有很多方法,静态代理类需要实现这些方法,然而我仅仅就想给每个方法加个日志而已。动态代理就很好的解决了这个问题

3.cglib动态代理

JDK动态代理中被代理的类必须实现接口,假如被代理类没有实现接口,我们不能强行的给它增加接口,那么cglib动态代理就可以解决这个问题

public class User {

    public void eat(String food) {
        System.out.println("eat " + food);
    }
}
public class UserInterceptor implements MethodInterceptor  {

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // TODO Auto-generated method stub
         System.out.println("预处理");
        return proxy.invokeSuper(obj, args);
    }

}
方法intercepor
public static void main(String[] args) {

        Enhancer enchancer = new Enhancer();// 字节码增强器
        enchancer.setSuperclass(User.class);// 设置被代理类为父类
        enchancer.setCallback(new UserInterceptor());// 设置回调
        User user = (User) enchancer.create();// 创建代理实例
        user.eat("葡萄");
    }
测试类
原文地址:https://www.cnblogs.com/ljjnbpy/p/9981218.html