JDK动态代理技术
JDK 动态是java原生自带的,区别于Cglib动态代理(Cglib动态代理已经集成到Spring-Core下了)| JDK 动态代理要求:目标类必须要有接口,通过接口生成一个代理类;
来看下jdk动态代理的实现方式:
原先的业务
- Calculator.java
package com.example;
/**
* 计算器接口
*/
public interface Calculator {
/**业务方法**/
public int add(int i, int j);
public int sub(int i, int j);
public float divide(int i, int j);
public int multi(int i, int j);
}
- CalculatorImpl.java
package com.example;
public class CalculatorImpl implements Calculator {
@Override
public int add(int i, int j) {
// 想打印输出参数
// 核心方法处理业务
int result = i + j;
// 想打印输出结果
return result;
}
@Override
public int sub(int i, int j) {
// 想打印输出参数
// 核心方法处理业务
int result = i - j;
// 想打印输出结果
return result;
}
@Override
public float divide(int i, int j) {
// 想打印输出参数
// 核心方法处理业务
int result = i / j;
// 想打印输出结果
return result;
}
@Override
public int multi(int i, int j) {
// 想打印输出参数
// 核心方法处理业务
int result = i * j;
// 想打印输出结果
return result;
}
}
- JDKProxyFactory.java
package com.example.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* JDK 动态代理
*/
public class JDKProxyFactory {
private Object target;
public JDKProxyFactory(Object target) {
this.target = target;
}
/**
* newProxyInstance(): 创建一个代理实例
* 其中有三个参数:
* 1、classLoader:加载动态生成的代理类的类加载器
* 2、interfaces:目标对象实现的所有接口的class对象所铸成的数组
* 3、invocationHandler:设置代理对象实现目标对象方法的过程,即代理类中如何重写接口中的抽象方法
*/
public Object getProxy() {
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
InvocationHandler invocationHandler = new InvocationHandler() {
/**
* invoke: 调用代理的方法都会执行此类方法,非核心业务 + 目标调用就行了
* proxy: 代理对象
* method: 代理对象需要实现的方法,即其中需要重写的方法
* args: method所对应方法的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
System.out.println("[动态代理][日志] " + method.getName() + " ,参数: " + Arrays.toString(args));
// 通过反射调用目标方法进行核心业务
result = method.invoke(target, args);
System.out.println("[动态代理][日志] " + method.getName() + " ,结果: " + result);
} catch (Exception e) {
e.printStackTrace();
System.out.println("[动态代理][日志] " + method.getName() + " ,异常: " + e.getMessage());
} finally {
System.out.println("[动态代理][日志] " + method.getName() + " ,方法执行完毕...");
}
return result;
}
};
/**
* JDK生成代理对象
* 参数1:类加载器
* 参数2:目标类的接口们
* 参数3:具体要进行的代理动作【非核心动作,调用目标方法】
*/
return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
- 测试
package com.example;
import com.example.dynamic.JDKProxyFactory;
public class Main {
public static void main(String[] args) {
/**
* JDK 动态代理测试
* 观察 JDKProxyFactory 类,发现需要new一个实例,然后调用它的proxy方法即可;
* 但是在new JDKProxyFactory构造时需要传入一个目标类
* 注意:因为JDK动态代理对象是通过接口来生成目标代理对象,因此必须先有一个目标接口
* 此种方式:即相当于我们把原先 CalculatorImpl 实现类中的额外功能 添加到 JDKProxyFactory 中了。
*/
// 1、构造Calculator目标类,这个相当于我们原先已有的业务实现逻辑对象
Calculator calculator = new CalculatorImpl();
// 2. 构造 JDKProxyFactory JDK 动态代理工厂方法
JDKProxyFactory proxyFactory = new JDKProxyFactory(calculator);
// 3. 调用 getProxy 创建一个代理实例,此处即 Calculator 的代理实例,
// 注意:此处一定要用 Calculator 接口来接收值,因为 getProxy 方法返回的是我们的 代理对象,不是目标对象(是我们目标对象的拜把子)
// 即相当于是我们接口的 另外一个实现类
Calculator calculatorProxy = (Calculator) proxyFactory.getProxy();
// 4. 通过动态代理生成的Calculator的代理对象去 代替 调用它的目标方法
calculatorProxy.add(3, 15);
}
}
本文来自博客园,作者:LoremMoon,转载请注明原文链接:https://www.cnblogs.com/hello-cnblogs/p/17789449.html