静态代理 动态代理 详解 附代码 动态代理和cglib

2018-7-21 Java 技术之动态代理机制 wingjay的博文写的很好 http://wingjay.com/2018/02/11/java-dynamic-proxy/
静态代理

package 设计模式.动态代理模式.wingjay博客黎姿.静态代理;

/**
 * Created by Administrator on 2018/7/21 0021.
 * http://wingjay.com/2018/02/11/java-dynamic-proxy/
 */
public class Main {
    public static void main(String[] args) {
        MyProxy myProxy = new MyProxy(new FunctionProvider());
        myProxy.doAThing();
    }

}

interface IFunction {
    void doAThing();
}

class FunctionProvider implements IFunction{
    @Override
    public void doAThing() {
        System.out.print("do A");
    }
}

class MyProxy implements IFunction {
    private FunctionProvider provider;
    MyProxy(FunctionProvider provider) {
        this.provider = provider;
    }
    @Override
    public void doAThing() {
        before();
        provider.doAThing();
    }

    private void before() {
        System.out.println("doAThing之前做些事情");
    }
}

看的视频https://www.bilibili.com/video/av18092969?from=search&seid=10237606488800747275
张三要相亲,父母作为代理类帮张三打理相亲事宜。用到JDK的接口InvocationHandler和Proxy类。
代理类Parent实现InvocationHandler接口,先拿到被代理对象的引用,可以添加before和after方法。中间才执行被代理对象的方法。
张三继承People接口,People接口里有相亲这个方法。父母拿到People对象的实例,表明可以帮助该对象执行方法,并且增强该方法,比如前期准备,相亲完办酒席等。
用JDK Proxy.newProxyInstance方法去创建代理类的实例,传入People接口,表示动态代理能代理接口中的方法,只要有方法是实现了该接口,并调用了该方法,都可以用Proxy.newProxyInstance生成代理对象。这个就是动态代理不同于静态代理的地方。静态代理中代理类有具体被代理类的引用,增强的是具体代理类的方法。而动态代理类能实现接口的方法,只要有类实现该接口,并且调用了该方法,动态代理就能生成具体的代理类,并增强该方法。

动态代理的好处是不用生产很多具体的代理类,下面例子中代理类代理的是接口People,在运行时才知道继承People接口的具体类,只要具体类中重写了People的方法,都会进行代理。

package 面试知识点.动态代理;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by Administrator on 2018/4/15 0015.
 */
public class Main {
    public static void main(String[] args) {
        ZhangSan zhangSan = new ZhangSan();
        People people =(People)Proxy.newProxyInstance(People.class.getClassLoader(), new Class[]{People.class}, new Parent(zhangSan));
        people.xiangqin();
    }
}


interface People {
    void xiangqin();
}

class Parent implements InvocationHandler {
    //代理类先拿到被代理对象的引用
    People people;

    public Parent(People people) {
        this.people = people;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        people.xiangqin();
        after();
        return null;
    }

    public void before() {
        System.out.println("相亲之前,父母帮忙准备相亲");
    }

    public void after() {
        System.out.println("相亲之后,父母帮忙结婚");
    }
}

class ZhangSan implements People {

    @Override
    public void xiangqin() {
        System.out.println("张三相亲");
    }
}

jdk的动态代理是如何调到invoke方法的?
动态打理中的invoke方法是在具体类的执行的时候进入的。可以打断点debug调试。
现在在People接口中再加一个方法,invoke在具体类执行xiangqin和eat方法的时候invoke得到的method是不同的,根据method不同可以执行不同的方法。

梁飞RPC 框架中invoke只是获得Provider服务的,没有执行自己的方法。

package 面试知识点.动态代理;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * Created by Administrator on 2018/4/15 0015.
 * //动态代理的好处是不用生产很多具体的代理类,下面例子中代理类代理的是接口People,在运行时才知道继承People接口的具体类,只要具体类中重写了People的方法,都会进行代理。
 */
public class Main {
    public static void main(String[] args) {
        ZhangSan zhangSan = new ZhangSan();
        People people =(People)Proxy.newProxyInstance(People.class.getClassLoader(), new Class[]{People.class}, new Parent(zhangSan));
        //people.xiangqin();
        people.eat();

        people =(People) Proxy.newProxyInstance(People.class.getClassLoader(), new Class[]{People.class}, new Parent(new LiSi()));

        people.xiangqin();
    }
}


interface People {
    void xiangqin();
    void eat();
}

class Parent implements InvocationHandler {
    //代理类先拿到被代理对象的引用
    People people;

    public Parent(People people) {
        this.people = people;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        if (method.getName().equals("xiangqin")) {
            people.xiangqin();
        } else if (method.getName().equals("eat")) {
            people.eat();
        }
        //people.xiangqin();
        //people.eat();
        after();
        return null;
    }

    public void before() {
        System.out.println("相亲之前,父母帮忙准备相亲");
    }

    public void after() {
        System.out.println("相亲之后,父母帮忙结婚");
    }
}

class ZhangSan implements People {

    @Override
    public void xiangqin() {
        System.out.println("张三相亲");
    }

    @Override
    public void eat() {
        System.out.println("张三吃饭");
    }
}

class LiSi implements People {
    @Override
    public void xiangqin() {
        System.out.println("李四失恋了,然后");
        System.out.println("李四相亲");
    }

    @Override
    public void eat() {
        System.out.println("李四吃饭");
    }
}

动态代理和cglib
AOP,面向切面编程,底层使用动态代理方式实现。针对实现了接口的类的横向扩展,采用的是JDK动态代理进行实现。在JDK动态代理中,为对原有类(实现了某一接口的类)进行横向扩展,内部创建了实现了同一接口的类代理对象,具有与原有类对象相同的功能,且进行了增强。对于未实现接口的类,想实现横向的扩展,则需要使用cglib动态代理实现,内部创建原有类的子类的代理对象,即在子类中调用父类的方法完成增强。
摘自 Spring框架自学之路——AOP https://blog.csdn.net/qq_15096707/article/details/79602676

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页