名称解释:
spring核心宗旨:简化开发
DI:依赖注入
IOC:控制反转(将实例化交给spring,用的时候直接在容器中取)
AOP:面向切面 (定义规则,实现解耦)
AOP核心宗旨:解耦
设计模式:
代理模式:
相关角色:执行者(比如:中介、黄牛),被代理人(比如:买房人、买票人)
满足条件:
1.对被代理人来说,事情必须做
2.自己不想做,没时间做,找代理
3.获取到被代理人的个人资料
【个人理解】:
代理模式的实现需要:实现了handler的代理人、被代理人、handler处理器、代理生成器
代理模式通俗来讲就是通过代理生成器生成一个代理类,自己不干的事情,交给代理类来干。
具体实现:主要的点在于代理生成器如何实现??
首先让我自己写应该是这样的:Proxy代理生成器里面有一个newProxyInstance()方法,里面有一个由代理人作为参数的构造方法。
这个方法是这样实现的:
1.根据被代理人的接口、类加载器、实现了handler的代理人,根据接口interfaces.getMethods()拿到所有的方法,循环遍历实现实现这些方法,方法的实现是通过调用handler.invoke()方法,通过反射机制clazz.getMethod拿到invoke的参数,同时将proxy作为参数作为invoke参数,这样以硬编码的方式写成一个代理类
2.将代理类写入磁盘生成为Java文件
3.编译Java文件为class文件
4.加载class文件到jvm
5.返回代理对象
代理生成器:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
// validate the parameters
// ...
// get the proxy class
Class<?> proxyClass = getProxyClass(loader, interfaces);
try {
// get the proxy class constructor that takes InvocationHandler as an argument
final Constructor<?> cons = proxyClass.getConstructor(new Class<?>[] { InvocationHandler.class });
// create a new proxy instance
return cons.newInstance(new Object[] { h });
} catch (Exception e) {
throw new IllegalArgumentException(e.toString());
}
}
生成的代理对象:
public class $Proxy0 implements Interface1, Interface2 {
private InvocationHandler h;
public $Proxy0(InvocationHandler h) {
this.h = h;
}
@Override
public void method1() throws Throwable {
h.invoke(this, Interface1.class.getMethod("method1"), null);
}
@Override
public void method2() throws Throwable {
h.invoke(this, Interface2.class.getMethod("method2"), null);
}
}
代理类:
public class MyInvocationHandler implements InvocationHandler {
private final Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method call");
Object result = method.invoke(target, args);
System.out.println("After method call");
return result;
}
}
使用:
import java.lang.reflect.Proxy;
public class ProxyExample {
public static void main(String[] args) {
HelloImpl helloImpl = new HelloImpl();
HelloInvocationHandler handler = new HelloInvocationHandler(helloImpl);
Hello proxyInstance = (Hello) Proxy.newProxyInstance(
helloImpl.getClass().getClassLoader(),
helloImpl.getClass().getInterfaces(),
handler
);
proxyInstance.sayHello();
}
}
- jdk动态代理的实现原理:
- 拿到被代理类的引用
- jdk代理自动实现一个类(这个类自动实现我们给的代理类的接口)
- 把被代理对象的引用拿到了(invoke允许你在代理对象上调用方法时插入自定义的行为。这种机制通常用于在调用实际对象的方法之前或之后执行一些操作,比如日志记录、性能监控、事务管理等)
- 重新动态生成一个class
- 编译
package com.bytesynch.gatekeeper.sink;
public interface Person {
void buyTickets();
String getName();
String getIDCard();
}
package com.bytesynch.gatekeeper.sink;
import lombok.Data;
@Data
public class XiaoMing implements Person{
private String name="小明";
private String IDCard="375666222";
@Override
public void buyTickets() {
System.out.println("需要买一张到南京的火车票");
System.out.println("时间是5月1号早上发车的");
System.out.println("想要个软卧下铺");
}
public static void main(String[] args) {
Person instance = (Person)new Huangniu().getInstance(new XiaoMing());
instance.buyTickets();
}
}
package com.bytesynch.gatekeeper.sink;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Huangniu implements InvocationHandler {
private Person target;//代理对象
public Object getInstance(Person person){
this.target=person;
Class<? extends Person> aClass = person.getClass();
//根据提供的被代理对象,生成一个代理类,该代理类实现了被代理类的所有接口
return Proxy.newProxyInstance(aClass.getClassLoader(),aClass.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(this.target.getName()+"买车票之前先做一下思想准备~");
System.out.println("-----------------------------------");
method.invoke(this.target,args);
System.out.println("-----------------------------------");
System.out.println("我买上票了黄牛还是靠谱的!");
return null;
}
}
小明买车票之前先做一下思想准备~
-----------------------------------
需要买一张到南京的火车票
时间是5月1号早上发车的
想要个软卧下铺
-----------------------------------
我买上票了黄牛还是靠谱的!
- CGLIB 代理
CGLIB(Code Generation Library)是一个强大的字节码生成库,它允许开发者在运行时动态地生成和操作Java类。与Java的标准动态代理机制(java.lang.reflect.Proxy
)不同,CGLIB不要求代理类实现接口,而是通过生成目标类的子类来实现代理。因此,CGLIB可以代理没有实现接口的类。下面我们将深入了解CGLIB是如何实现代理的
CGLIB代理的基本工作原理
CGLIB通过继承目标类并重写其方法来实现代理。当方法被调用时,CGLIB代理类会拦截调用,并可以在方法调用前后添加自定义逻辑。
CGLIB的关键组件
- Enhancer:用于生成代理类的主要类。
- MethodInterceptor:用于拦截方法调用的接口。
CGLIB代理的实现步骤
- 创建Enhancer对象:
Enhancer
是CGLIB的核心类,用于生成代理类。 - 设置父类:代理类将继承目标类。
- 设置回调:使用
MethodInterceptor
拦截方法调用。 - 生成代理实例:通过
create
方法生成代理实例。
被代理类
public class SampleClass {
public void test() {
System.out.println("Hello, world!");
}
}
代理类
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class SampleMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method call");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method call");
return result;
}
}
使用Enhancer创建代理类
import org.springframework.cglib.proxy.Enhancer;
public class CglibExample {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(SampleClass.class);
enhancer.setCallback(new SampleMethodInterceptor());
SampleClass proxy = (SampleClass) enhancer.create();
proxy.test();
}
}
CGLIB代理生成器如何生成代理类
CGLIB通过以下步骤生成代理类:
- 设置类加载器:确定生成代理类时使用的类加载器。
- 设置父类:代理类将继承目标类。
- 设置回调:定义方法调用时的拦截逻辑。
- 生成代理类字节码:使用 ASM 动态生成代理类的字节码。
- 定义并加载代理类:通过类加载器加载代理类。
- 创建代理实例:通过代理类的构造函数创建代理实例。
大概的生成器Enhancer的代码
1. 设置类加载器
Enhancer
使用默认的类加载器,也可以通过 setClassLoader
方法设置自定义的类加载器。
public void setClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
2. 设置父类
代理类将继承目标类。通过 setSuperclass
方法设置目标类。
public void setSuperclass(Class<?> superclass) {
this.superclass = superclass;
}
3. 设置回调
定义方法调用时的拦截逻辑。通过 setCallback
方法设置 MethodInterceptor
实现
public void setCallback(Callback callback) {
this.callback = callback;
}
4. 生成代理类字节码
使用 ASM 库生成代理类的字节码。代理类继承目标类,并重写其方法
private byte[] generateClass() {
ClassEmitter ce = new ClassEmitter();
// 设置类名、父类和接口
ce.begin_class(Opcodes.V1_8, Opcodes.ACC_PUBLIC, className, superclass.getName(), null, "<generated>");
// 添加字段
ce.visitField(Opcodes.ACC_PRIVATE, "CGLIB$CALLBACK_0", Type.getDescriptor(MethodInterceptor.class), null, null);
// 添加构造函数
CodeEmitter e = ce.begin_method(Opcodes.ACC_PUBLIC, new Method("<init>", "()V"), null);
e.load_this();
e.super_invoke_constructor();
e.return_value();
e.end_method();
// 重写方法
for (Method method : superclass.getDeclaredMethods()) {
if (Modifier.isFinal(method.getModifiers())) {
continue;
}
e = ce.begin_method(Opcodes.ACC_PUBLIC, method, null);
e.load_this();
e.getfield("CGLIB$CALLBACK_0");
e.load_this();
e.load_args();
e.invoke_interface(MethodInterceptor.class, "intercept");
e.return_value();
e.end_method();
}
ce.end_class();
return ce.toByteArray();
}
5. 定义并加载代理类
使用类加载器加载生成的代理类字节码。
private Class<?> defineClass(byte[] classBytes) throws Exception {
ClassLoader loader = classLoader != null ? classLoader : getClass().getClassLoader();
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class);
defineClass.setAccessible(true);
return (Class<?>) defineClass.invoke(loader, null, classBytes, 0, classBytes.length);
}
6. 创建代理实例
通过代理类的构造函数创建代理实例,并将 MethodInterceptor
赋值给代理实例的回调字段。
public Object create() throws Exception {
byte[] classBytes = generateClass();
Class<?> proxyClass = defineClass(classBytes);
Object proxyInstance = proxyClass.getDeclaredConstructor().newInstance();
Field callbackField = proxyClass.getDeclaredField("CGLIB$CALLBACK_0");
callbackField.setAccessible(true);
callbackField.set(proxyInstance, callback);
return proxyInstance;
}
生成的代理类的伪代码
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class SampleClass$$EnhancerByCGLIB$$ extends SampleClass {
// CGLIB 用于存储回调对象的字段
private MethodInterceptor CGLIB$CALLBACK_0;
// 默认构造函数
public SampleClass$$EnhancerByCGLIB$$() {
super();
}
// 重写目标方法 test()
@Override
public void test() {
try {
// 获取 MethodProxy 对象
MethodProxy methodProxy = MethodProxy.find(SampleClass.class, "test");
// 调用 MethodInterceptor 的 intercept 方法
CGLIB$CALLBACK_0.intercept(this, SampleClass.class.getMethod("test"), null, methodProxy);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
// 用于设置回调对象的方法
public void setCallback(MethodInterceptor callback) {
this.CGLIB$CALLBACK_0 = callback;
}
}
注意:cglib和jdk的动态代理基本思想都是一样的,不同点在于如何生成代理对象上,
jdk是实现一个接口,通过反射的方式Method.invoke()调用被代理类的方法
cglib是代理类生成器,给他生成了一个子类,通过设置回调方法设置定义的MethodInterceptor ,通过它的调用ntercept 方法,其中参数
Object obj, Method method, Object[] args, MethodProxy proxy
第一个参数为生成的子类
第二个参数为Method
第三个参数为method参数
第四个参数为:
MethodProxy methodProxy = MethodProxy.find(SampleClass.class, "test");
public class MethodProxy {
private final Method originalMethod;
private final Method proxyMethod;
private MethodProxy(Method originalMethod, Method proxyMethod) {
this.originalMethod = originalMethod;
this.proxyMethod = proxyMethod;
}
public static MethodProxy find(Class<?> superClass, String methodName, Class<?>[] parameterTypes) {
try {
Method originalMethod = superClass.getDeclaredMethod(methodName, parameterTypes);
Method proxyMethod = findProxyMethod(superClass, methodName, parameterTypes);
return new MethodProxy(originalMethod, proxyMethod);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
public Object invokeSuper(Object obj, Object[] args) throws Throwable {
return proxyMethod.invoke(obj, args);
}
private static Method findProxyMethod(Class<?> superClass, String methodName, Class<?>[] parameterTypes) {
// 这里实现查找代理方法的逻辑,通常通过 CGLIB 预生成的字节码查找
// 此处简化为直接调用父类方法
return superClass.getDeclaredMethod(methodName, parameterTypes);
}
}
- AspectJ
TODO待补充