什么是动态代理?
动态代理是 Java 提供的一种在运行时动态创建代理类和对象的技术。它允许你在不修改原始类代码的情况下,通过一个代理对象来控制对原始对象的访问。也就是代理可以无侵入式的给对象增强其他的功能。
需要注意的是:是通过接口来保证代理的样子的,后面的对象和代理需要实现同一个接口,接口里面就是需要被代理的所有方法。
动态代理的核心组件
java.lang.reflect.Proxy 类 - 用于创建动态代理类和实例
java.lang.reflect.InvocationHandler 接口 - 代理对象的调用处理器
image.png
代码如下:
下面的代码给 BigStar 里面的唱歌跳舞方法增加了功能,完整代码如下:
Star 接口 - 里面是需要被代理的方法
package com.动态代理_基础最终章;
public interface Star {
// 对象和代理都需要实现这个接口,这个接口里面的方法都需要被代理
// 唱歌
public abstract String sing(String name);
// 跳舞
public abstract void dance();
}
BigStar 类,这个类实例化的对象需要被代理
package com.动态代理_基础最终章;
public class BigStar implements Star{
private String name;
public BigStar() {
}
public BigStar(String name) {
this.name = name;
}
// 唱歌
@Override
public String sing(String name) {
System.out.println(this.name + "正在唱" + name);
return "唱完了,说声谢谢";
}
// 跳舞
@Override
public void dance(){
System.out.println(this.name + "在跳舞");
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
public String toString() {
return "BigStar{name = " + name + "}";
}
}
ProxyUtil 类 - 用于创建一个代理对象
package com.动态代理_基础最终章;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 类的作用:
* 创建一个代理
*/
public class ProxyUtil {
public static Star createProxy(BigStar bigStar) {
Star o = (Star) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(), // 参数一:用于指定用哪个类加载器去加载生成的代理类
new Class[]{Star.class}, // 参数二:指定接口,接口里面是需要代理的方法
// 参数三:用来指定生成的代理对象要干什么
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 唱歌跳舞方法前要执行的逻辑
if("sing".equals(method.getName())) {
System.out.println("唱歌前要准备话筒。。。");
}else if("dance".equals(method.getName())) {
System.out.println("跳舞前要准备场地。。。");
}
// 执行原始对象里面的方法
return method.invoke(bigStar, args);
}
}
);
return o;
}
}
测试类
package com.动态代理_基础最终章;
public class test {
public static void main(String[] args) {
// 需要代理的对象
BigStar bigStar = new BigStar("xx明星");
// 代理这个对象
Star proxy = ProxyUtil.createProxy(bigStar);
// 调用代理的方法 - 唱歌
String res = proxy.sing("月亮之上");
System.out.println(res);
// 调用代理的方法 - 跳舞
proxy.dance();
}
}
扩展 - jdk 代理
spring aop 动态代理模式有用的
public class ProxyFactory {
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
public Object getProxy(){
/**
* newProxyInstance():创建一个代理实例
* 其中有三个参数:
* 1、classLoader:加载动态生成的代理类的类加载器
* 2、interfaces:目标对象实现的所有接口的class对象所组成的数组
* 3、invocationHandler:设置代理对象实现目标对象方法的过程,即代理类中如何重写接口中的抽象方法
*/
ClassLoader classLoader = target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* proxy:代理对象
* method:代理对象需要实现的方法,即其中需要重写的方法
* args:method所对应方法的参数
*/
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;
}
};
return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
}
}
测试类
@Test
public void testDynamicProxy(){
ProxyFactory factory = new ProxyFactory(new CalculatorLogImpl());
Calculator proxy = (Calculator) factory.getProxy();
proxy.div(1,0);
//proxy.div(1,1);
}
参考:
黑马java教程
尚硅谷新版SSM框架教程









网友评论