参考视频:
AOP:https://www.bilibili.com/video/BV1Vf4y127N5?p=25
cglib:https://www.bilibili.com/video/BV1G4411c7N4?p=94&vd_source=22e1d00fb0d54df3638f9bf26476387a
示例1:
@Slf4j
public class LoginJdkProxy {
public static void main(String[] args) {
Login loginProxy = (Login) Proxy.newProxyInstance(
LoginJdkProxy.class.getClassLoader(),
new Class[]{Login.class},
new InvocationHandler() {
Login login = new LoginImpl();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("将要执行方法:{},参数:{}", method, Arrays.toString(args));
//如果是登录方法
if ("login".equals(method.getName())) {
if (StringUtils.isEmpty(args[0])) {
return "用户名不能为空!";
}
Object invoke = method.invoke(login, args);
return invoke;
}
return method.invoke(login, args);
}
});
System.out.println(loginProxy.login("admin", "123"));
System.out.println(loginProxy.login("", "123"));
System.out.println(loginProxy.toString());
}
}
interface Login {
String login(String username, String password);
}
class LoginImpl implements Login {
@Override
public String login(String username, String password) {
if ("admin".equals(username)) {
return "登录成功...";
}
return "登录失败...";
}
}
示例2:
既然有接口就能代理,那HashMap应该是可以被代理的!因为有接口Map
public class HashMapJdkProxy {
public static void main(String[] args) {
Map<String, String> myHashMap = (Map<String, String>) Proxy.newProxyInstance(
HashMapJdkProxy.class.getClassLoader(),
new Class[]{Map.class},
new HashMapInvocationHandler(new HashMap<>()));
myHashMap.put("aa", "死了");
String aa = myHashMap.get("aa");
System.out.println(aa); // **了
}
}
class HashMapInvocationHandler implements InvocationHandler {
HashMap<String, String> hashMap;
public HashMapInvocationHandler(HashMap<String, String> hashMap) {
this.hashMap = hashMap;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强get方法
if ("get".equals(method.getName())) {
//如果获得的内容含有‘死’,则替换为‘**’
String res = (String) method.invoke(hashMap, args);
return res.replaceAll("死", "**");
}
return method.invoke(hashMap, args);
}
}
例如:
public class HashMapCglibProxy {
public static void main(String[] args) {
//创建一个代理对象
// 1、工具类
Enhancer enhancer = new Enhancer();
// 2、设置父类
enhancer.setSuperclass(HashMap.class);
// 3、设置回调函数
enhancer.setCallback(new MethodInterceptor() {
//定义一个成员变量,后面使用反射执行方法
HashMap hashMap = new HashMap();
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.printf("调用的方法是%s, 参数有:%s\n",method.getName(), Arrays.toString(objects));
if ("get".equals(method.getName())){
String res = (String) method.invoke(hashMap, objects);
return res + " 已被增强!";
}
return method.invoke(hashMap,objects);
}
});
// 4、创建对象
HashMap myHashMap = (HashMap) enhancer.create();
//调用代理对象的方法
myHashMap.put("key","val");
Object key = myHashMap.get("key");
System.out.println(key);
}
}
就是每次是否在方法区产生新的class,默认是true,在这种情况下,只要是代理同一个类型的对象,就不会产生新的class;而如果设为false,那么每次创建代理对象,他们的class都是不同的。如果设为false 可引发 OOM ,原因是Metaspace满了。
例如:
public class RegisterCglibProxy {
public static void main(String[] args) {
Enhancer enhancer1 = getEnhancer();
Enhancer enhancer2 = getEnhancer();
System.out.println("enhancer1.create().getClass() --> " + enhancer1.create().getClass());
System.out.println("enhancer2.create().getClass() --> " + enhancer2.create().getClass());
Register register1 = (Register) enhancer1.create();
Register register2 = (Register) enhancer1.create();
System.out.println("register1.getClass() --> " + register1.getClass());
System.out.println("register2.getClass() --> " + register2.getClass());
System.out.println(register1.register(""));
System.out.println(register2.register("1232@qq.com"));
}
private static Enhancer getEnhancer() {
Register register = new Register();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Register.class);
enhancer.setUseCache(false);
enhancer.setCallback((MethodInterceptor) (o, method, objects, methodProxy) -> method.invoke(register, objects));
return enhancer;
}
}
class Register {
public boolean register(String qq) {
return !StringUtils.isEmpty(qq);
}
}
当enhancer.setUseCache(false)时:每创建一个对象,class都是不一样的。
当enhancer.setUseCache(true)或者不设置时:每创建一个对象,class都是一样的。