java中的动态代理分为两种
- JDK动态代理 只提供接口的代理,不支持类的代理 核心是InvocationHandler和Proxy,在InvocationHandler中通过反射调用目标类的代码。我们可以在其前后加上我们自己的业务。
- CGLIB动态代理 如果代理类没有实现InvocationHandler接口,会采用此方式。CGLIB是一个代码类库,可以在运行时动态指定一个类的子信息。覆盖其中的方法并在其中写我们的业务。
CGLIB实现
1.写一个类作为增强对象
/**
* @className: UserService
* @description: game接口
* @date: 2022/07/23
* @author: Sora33
*/
public class GameService {
void playing() {
System.out.println("游戏中……");
}
void eat() {
System.out.println("吃饭中……");
}
}
2.主方法进行测试
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* @className: CgLibTest
* @description: CgLibTest
* @date: 2022/07/23
* @author: Sora33
*/
public class CgLibTest {
private static Logger logger = LoggerFactory.getLogger(CgLibTest.class);
public static void main(String[] args) {
GameService gameService = new GameService();
// 创建一个增强器类
Enhancer enhancer = new Enhancer();
// 设置父类,可以理解为我们增强的类
enhancer.setSuperclass(GameService.class);
// 设置callback属性
enhancer.setCallback(new MethodInterceptor() {
// 重写interceptor方法
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
boolean methodName = method.getName().equals("playing");
if (methodName) {
// 如果是正在玩游戏就执行此逻辑
logger.info("正在检测状态");
methodProxy.invoke(gameService, objects);
logger.info("游戏结束");
return null;
} else {
logger.info("正在检测状态");
methodProxy.invoke(gameService, objects);
logger.info("并没有玩游戏");
return null;
}
}
});
GameService game = (GameService)enhancer.create();
game.playing();
game.eat();
}
}
3.执行结果
10:30:35.334 [main] INFO com.sora.CgLibTest - 正在检测状态
游戏中……
10:30:35.347 [main] INFO com.sora.CgLibTest - 游戏结束
10:30:35.347 [main] INFO com.sora.CgLibTest - 正在检测状态
吃饭中……
10:30:35.347 [main] INFO com.sora.CgLibTest - 并没有玩游戏
JDK实现
1.先建一个car的接口
public interface Car {
void run();
}
2.然后是实现类
public class CarImpl implements Car {
@Override
public void run() {
System.out.println("准备上高速");
}
}
3.(关键)写一个类,实现InvocationHandler接口
invoke是执行接口中的方法。我们需要在前后加上我们自己的操作
public class MyInvokeTest implements InvocationHandler {
private Object object;
public MyInvokeTest(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置操作
System.out.println("车子正在启动");
// 执行方法
Object invoke = method.invoke(object, args);
// 后置操作
System.out.println("到达目的地");
return invoke;
}
}
4. 写一个测试类进行测试
public class JDKTest {
public static void main(String[] args) {
// 创建car实现类对象
CarImpl car = new CarImpl();
// 创建InvocationHandler对象
InvocationHandler invocationHandler = new MyInvokeTest(car);
// 代理
Car instance = (Car)Proxy.newProxyInstance(
car.getClass().getClassLoader(), // 类加载器
car.getClass().getInterfaces(), // 目标接口
invocationHandler); // 完成代理模式的处理器
// 执行
instance.run();
}
}
5.打印结果
车子正在启动
准备上高速
到达目的地
更多知识请移步个人博客:33sora.com