目录
一、代理模式
常用的代理模式有,jdk动态代理s和CGLIB动态代理模式,JDK动态代理是java.lang.reflect.*包提供的方式,它必须提供一个接口才能产生代理对象。
下面讲解jdk动态代理,如下图:
假设有这样一个场景,你的公司是一个软件公司,你是一位软件工程师,客户带着需求过来,显然不会先去直接找你,而是去找一个叫商务对象的人,此时商务就是代理你的人,同时也是与客户交谈的人。
下面看一个案例:
第一步,先定义一个接口:
package com.hand.proxy;
public interface HelloWorld {
public void sayHelloWorld();
public void sayHai();
}
第二步,实现该接口:
package com.hand.proxy;
public class HelloWorldImpl implements HelloWorld {
public void sayHelloWorld() {
System.out.println("hello world!");
}
public void sayHai() {
System.out.println("您好,我要代理!");
}
}
第三步,创建代理类,实现InvocationHandler接口,实现invoke方法
package com.hand.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKExampleProxy implements InvocationHandler{
private Object target=null;
/**
* 生成代理对象的方法
*/
public Object bind(Object target) {
this.target=target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
/**
* proxt为代理对象,就是bind方法生成的对象
* method为当前调度的方法
* args为调度方法的参数
*/
public Object invoke(Object proxy,
Method method,
Object[] args) throws Throwable {
System.out.println("进入代理方法!");
System.out.println("在调度真实方法之前的服务!");
//在调度真实方法前可以通过此方法执行其他的方法逻辑,此处甚至可以不调用helloWorld打印
Object obj=method.invoke(target, args);
//返回执行的结果
return obj;
}
}
验证:
package com.hand.proxy;
public class test01 {
public static void main(String[]args) {
JDKExampleProxy jdk=new JDKExampleProxy();
//创建代理对象
HelloWorld proxy=(HelloWorld) jdk.bind(new HelloWorldImpl());
proxy.sayHelloWorld();
proxy.sayHai();
}
}
打印结果:
进入代理方法!
在调度真实方法之前的服务!
hello world!
进入代理方法!
在调度真实方法之前的服务!
您好,我要代理!
由此可以发现,在执行真实的方法前后,我们还可以添加其他逻辑,jdk动态代理必须实现java.lang.reflect.InvocationHandler类,由此商务控制了客户对软件工程师的访问!代理模式可以增加了对实际访问对象的扩展。
CGLIB代理与JDK动态代理模式的区别:jdk需要实现接口,而CGLIB代理模式不需要实现接口来实现代理。
二、JDK动态代理的应用
mybatis的Mapper接口的工作原理就是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,转而执行mapperStatement所代表的sql,然后将sql执行结果返回。
三、面试
1. 什么是jdk动态代理?
jdk动态代理是基于java反射技术实现的一种通过实现目标接口来创建代理对象的一种代理方式。
四、Dubbo源码用到的JDK动态代理
DubboNamespaceHandler
ReferenceBean.getObject
createProxy(map)
动态代理InvocationHandler
通过动态代理JDKProxyFactory 创建代理工厂ProxyFactory。
在JDKProxyFactory里用到了JDK动态代理模式。