静态代理
- 实现
代理类与目标类实现相同的接口
- 代理类
package com.tmq.designmodeldemo.proxy.staticproxy;
import com.tmq.designmodeldemo.proxy.dynamic.IGamePlayer;
/**
* 静态代理
* 和代理对象实现相同的接口
* @Author tangmqb DCITS
* @DATE 2020/7/31 16:19
* @Version 1.0.0
*/
public class GameplayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer;
public GameplayerProxy(IGamePlayer gamePlayer) {
this.gamePlayer = gamePlayer;
}
@Override
public void login(String userName) {
System.out.println("游戏代理登录了,静态代理开始");
gamePlayer.login(userName);
}
@Override
public void killBoss() {
gamePlayer.killBoss();
}
@Override
public void updateGrade() {
System.out.println("打怪结束,游戏代练完了,收费:$150");
gamePlayer.updateGrade();
}
}
静态代理比较简单,不做过多描述
动态代理
-
JDK代理 java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用
InvokeHandler
来处理。 -
Cglib代理 利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成
子类
来处理 -
jdk代理
package com.tmq.designmodeldemo.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @Author tangmqb DCITS
* @DATE 2020/7/31 15:52
* @Version 1.0.0
*/
public class MyInvoketionHandle implements InvocationHandler {
private Object target ;
public MyInvoketionHandle(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("游戏代练...");
Object invoke = method.invoke(this.target , args);
return invoke;
}
}
测试
package com.tmq.designmodeldemo.proxy.dynamic;
import java.lang.reflect.Proxy;
/**
* @Author tangmqb DCITS
* @DATE 2020/7/31 15:55
* @Version 1.0.0
*/
public class ProxyClient1 {
public static void main(String[] args) {
GamePlayer gamePlayer = new GamePlayer();
MyInvoketionHandle handle = new MyInvoketionHandle(gamePlayer);
//这里只能强转接口类
IGamePlayer proxy =(IGamePlayer) Proxy.newProxyInstance(gamePlayer.getClass().getClassLoader(), gamePlayer.getClass().getInterfaces(), handle);
proxy.login("不差钱");
proxy.killBoss();
proxy.updateGrade();
}
}
- Cglib代理
/**
* @author tangmqb
* @version 1.0.0
* 2022/3/10
*/
public class CglibProxy implements MethodInterceptor {
private Object target;
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("代理:先收钱");
Object invoke = method.invoke(target, objects);
System.out.println("代理结束");
return invoke;
}
//定义获取代理对象方法
public Object getCglibProxy(Object objectTarget){
//为目标对象target赋值
this.target = objectTarget;
Enhancer enhancer = new Enhancer();
//设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类
enhancer.setSuperclass(objectTarget.getClass());
enhancer.setCallback(this);// 设置回调
Object result = enhancer.create();//创建并返回代理对象
return result;
}
public static void main(String[] args) {
CglibProxy cglib = new CglibProxy();//实例化CglibProxy对象
PlayGame game = (PlayGame)cglib.getCglibProxy(new PlayGame());
game.playGame();
}
}
class PlayGame{
public void playGame(){
System.out.println("Play Game");
}
}
测试结果
代理:先收钱
Play Game
代理结束
总结
如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
如果目标对象实现了接口,可以强制使用CGLIB实现AOP
如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换