我们举个很常见的例子: 工厂会生产很多的玩具, 但是我们买玩具都是到商店买的, 而不是到工厂去买的, 工厂怎么生产我们并不关心, 我们只知道到商店可以买到自己想要的玩具,并且,如果我们需要送人的话商店可以把这些玩具使用礼品盒包装。这个工厂就是委托类, 商店就是代理类, 我们就是客户类。
Java 静态代理 编译期间就已经确定 只适用委托方法少
// 委托接口
public interface IHelloService {
/**
* 定义接口方法
* @param userName
* @return
*/
String sayHello(String userName);
}
// 委托类实现 工厂
public class HelloService implements IHelloService {
@Override
public String sayHello(String userName) {
System.out.println("helloService" + userName);
return "HelloService" + userName;
}
}
// 代理类 商店
public class StaticProxyHello implements IHelloService {
private IHelloService helloService = new HelloService();
@Override
public String sayHello(String userName) {
/** 代理对象可以在此处包装一下*/
System.out.println("代理对象包装礼盒...");
return helloService.sayHello(userName);
}
}
// 测试静态代理类
public class MainStatic {
public static void main(String[] args) {
StaticProxyHello staticProxyHello = new StaticProxyHello();
staticProxyHello.sayHello("isole");
}
}
动态代理技术
在 Java 的动态代理中, 主要涉及 2 个类
,java.lang.reflect.Proxy
java.lang.reflect.InvocationHandler 中间类 (实现了 InvocationHandler 的类) 有一个委托类对象引用
public interface InvocationHandler {
/**
* 调用处理
* @param proxy 代理类对象
* @param methon 标识具体调用的是代理类的哪个方法
* @param args 代理类方法的参数
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
demo
// 委托类接口
public interface IHelloService {
/**
* 方法1
* @param userName
* @return
*/
String sayHello(String userName);
/**
* 方法2
* @param userName
* @return
*/
String sayByeBye(String userName);
}
// 委托类 工厂
public class HelloService implements IHelloService {
@Override
public String sayHello(String userName) {
System.out.println(userName + " hello");
return userName + " hello";
}
@Override
public String sayByeBye(String userName) {
System.out.println(userName + " ByeBye");
return userName + " ByeBye";
}
}
// 中间类 商店
public class JavaProxyInvocationHandler implements InvocationHandler {
/**
* 中间类持有委托类对象的引用,这里会构成一种静态代理关系
*/
private Object obj ;
/**
* 有参构造器,传入委托类的对象
* @param obj 委托类的对象
*/
public JavaProxyInvocationHandler(Object obj){
this.obj = obj;
}
/**
* 动态生成代理类对象,Proxy.newProxyInstance
* @return 返回代理类的实例
*/
public Object newProxyInstance() {
return Proxy.newProxyInstance(
//指定代理对象的类加载器
obj.getClass().getClassLoader(),
//代理对象需要实现的接口,可以同时指定多个接口
obj.getClass().getInterfaces(),
//方法调用的实际处理者,代理对象的方法调用都会转发到这里
this);
}
/**
*
* @param proxy 代理对象
* @param method 代理方法
* @param args 方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoke before");
Object result = method.invoke(obj, args);
System.out.println("invoke after");
return result;
}
}
// 测试动态代理类
public class MainJavaProxy {
public static void main(String[] args) {
JavaProxyInvocationHandler proxyInvocationHandler = new JavaProxyInvocationHandler(new HelloService());
IHelloService helloService = (IHelloService) proxyInvocationHandler.newProxyInstance();
helloService.sayByeBye("paopao");
helloService.sayHello("yupao");
}
}
Java 动态代理其实内部是通过反射机制实现的
CGLIB 动态代理
JDK 动态代理依赖接口实现,而当我们只有类没有接口的时候就需要使用另一种动态代理技术 CGLIB 动态代理
原理是对指定的委托类(工厂)生成一个子类并重写其中业务方法来实现代理
查找目标类上的所有非 final 的 public 类型的方法 (final 的不能被重写)
将这些方法的定义转成字节码
将组成的字节码转换成相应的代理的 Class 对象然后通过反射获得代理类的实例对象
实现 MethodInterceptor 接口, 用来处理对代理类(商店)上所有方法的请求
// 委托类,是一个简单类
public class CglibHelloClass {
/**
* 方法1
* @param userName
* @return
*/
public String sayHello(String userName){
System.out.println("目标对象的方法执行了");
return userName + " sayHello";
}
public String sayByeBye(String userName){
System.out.println("目标对象的方法执行了");
return userName + " sayByeBye";
}
}
/**
* CglibInterceptor 用于对方法调用拦截以及回调
*
*/
public class CglibInterceptor implements MethodInterceptor {
/**
* CGLIB 增强类对象,代理类对象是由 Enhancer 类创建的,
* Enhancer 是 CGLIB 的字节码增强器,可以很方便的对类进行拓展
*/
private Enhancer enhancer = new Enhancer();
/**
*
* @param obj 被代理的对象
* @param method 代理的方法
* @param args 方法的参数
* @param proxy CGLIB方法代理对象
* @return cglib生成用来代替Method对象的一个对象,使用MethodProxy比调用JDK自身的Method直接执行方法效率会有提升
* @throws Throwable
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("方法调用之前");
Object o = proxy.invokeSuper(obj, args);
System.out.println("方法调用之后");
return o;
}
/**
* 使用动态代理创建一个代理对象
* @param c
* @return
*/
public Object newProxyInstance(Class<?> c) {
/**
* 设置产生的代理对象的父类,增强类型
*/
enhancer.setSuperclass(c);
/**
* 定义代理逻辑对象为当前对象,要求当前对象实现 MethodInterceptor 接口
*/
enhancer.setCallback(this);
/**
* 使用默认无参数的构造函数创建目标对象,这是一个前提,被代理的类要提供无参构造方法
*/
return enhancer.create();
}
}
//测试类
public class MainCglibProxy {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
CglibHelloClass cglibHelloClass = (CglibHelloClass) cglibProxy.newProxyInstance(CglibHelloClass.class);
cglibHelloClass.sayHello("isole");
cglibHelloClass.sayByeBye("sss");
}
}