The role of dynamic proxy: to achieve method enhancement without modifying the source code.
Dynamic code:
- Features: Bytecode can be created and loaded whenever it is used
- Function: Add functions to the method without changing the source code Category
: - Interface-based dynamic proxy
- Subclass-based dynamic proxies
Interface-based dynamic proxy
Interface-based dynamic proxy:
- Class involved: Proxy
- Provider: JDK official
- How to create a proxy object:
-
使用Proxy中的newProxyInstance方法
-
- Requirements for creating proxy objects:
-
被代理类至少实现一个接口,如果没有则不能创建
-
- Parameters of the newProxyInstance method:
-
ClassLoader: 类加载器
-
它是用于加载代理对象字节码的。和被代理对象使用相同的类加载器
-
- class[]: bytecode array
-
它是让代理对象和被代理对象有相同的方法
-
- InvocationHandler: used to provide enhanced code
-
它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
-
此接口的实现类都是谁用谁写。
-
Create Iproduct interface
public interface Iprodouct {
public void saleComputer(Float money);
public void afterSale(Float money);
}
Create an implementation class distribute
public class distributor implements Iprodouct {
@Override
public void saleComputer(Float money) {
System.out.println("卖出去了一台电脑:" + money);
}
@Override
public void afterSale(Float money) {
System.out.println("经过售后赚了:" + money);
}
}
Create user tests
public class client {
public static void main(String[] args) {
distributor distributor = new distributor();
Iprodouct proxyProdouce = (Iprodouct) Proxy.newProxyInstance(distributor.getClass().getClassLoader(),
distributor.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 作用:执行被代理对象的任何接口方法都会经过该方法
* 方法参数的含义
* @param proxy 代理对象的引用
* @param method 当前执行的方法
* @param args 当前执行方法所需的参数
* @return 和被代理对象方法有相同的返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 提供增强的代码
Object returnValue = null;
// 1、获取代码执行的参数
Float money = (Float)args[0];
// 2、判断当前方法是否是销售
if ("saleComputer".equals(method.getName())) {
returnValue = method.invoke(distributor, money*0.8f);
}
return returnValue;
}
});
proxyProdouce.saleComputer(10000f);
}
}
Subclass-based dynamic proxies
- Class involved: Enhancer
-
提供者:cglib第三方
-
- How to create a proxy object:
-
使用Enhancer中的create方法
-
- Requirements for creating proxy objects:
-
被代理类不能是最终类
-
- The parameters of the create method:
-
Class:字节码
-
它是用于指定被代理对象的字节码。
-
- Callback: used to provide enhanced code
-
它是让我们写如何代理。我们一般都是些一个该接口的实现类,通常情况下都是匿名内部类,但不是必须的。
-
此接口的实现类都是谁用谁写。
-
我们一般写的都是该接口的子接口实现类:MethodInterceptor
-
Create the distribute class
public class distributor{
public void saleComputer(Float money) {
System.out.println("卖出去了一台电脑:" + money);
}
public void afterSale(Float money) {
System.out.println("经过售后赚了:" + money);
}
}
implement test
public class clientCglib {
public static void main(String[] args) {
distributor distributor = new distributor();
distributor dis = (distributor) Enhancer.create(distributor.getClass(), new MethodInterceptor() {
/**
*
* @param o 增强对象
* @param method 增强的方法
* @param objects 参数值
* @param methodProxy 当前执行方法的执行对象
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
// 提供增强的代码
Object returnValue = null;
// 1、获取代码执行的参数
System.out.println(objects[0]);
Float money = (Float) objects[0];
// 2、判断当前方法是否是销售
if ("saleComputer".equals(method.getName())) {
returnValue = method.invoke(distributor, money * 0.8f);
}
return returnValue;
}
});
dis.saleComputer(1000f);
}
}