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