我现在正在读一本用韩语写的春季书,我的英语很糟糕。请理解。
在书中,它说Spring的AOP如果使用Interface,则使用动态代理启动类,如果不使用Interface,则使用CGLIB启动类。我不太清楚这是什么意思。你能帮我理解它的深层含义吗?
我不知道这个问题是否愚蠢。但我只是好奇 THX。
代理本质上是客户端和对象之间的中介,因此它实现了对象的非最终方法。代理接口相对简单,因为接口只是需要实现的方法列表,便于拦截方法调用。
Java 中的Proxy类是一个实现在运行时指定的接口列表的类。然后,代理有一个与之关联的InvocationHandler,它将代理上的方法调用委托给被代理的对象。它充当间接级别,这样方法不会在对象本身上调用,而是在其代理上调用。只有InvocationHandler
一个需要实现的方法:
public Object invoke(Object proxy, Method method, Object[] args)
同时,调用该方法的客户端无法分辨代理及其底层对象表示之间的区别,它也不应该关心。
与接口相比,动态代理类并不那么简单。虽然 JavaProxy
只是一个接口或一组接口的运行时实现,但对象不必实现接口。因此,代理类需要生成字节码,这就是 cglib 等库发挥作用的地方。cglib 提供对代理类的支持,因为它可以动态生成字节码(即类文件),这意味着它可以在运行时以 JavaProxy
可以在运行时实现接口的方式扩展类。
代理有很多用途。一种这样的用途是延迟加载。延迟加载允许仅在需要时加载对象图中的对象。我们可以在需要访问它们时即时加载它们,而不是立即将它们全部加载到内存中,这可能是昂贵且资源密集的,例如迭代对象集合。我们不是加载整个集合,而是一次加载一个小集合。这可以通过代理来实现。代理代表延迟加载的对象。对象本身(可能是从数据库加载的)在其代理上调用方法之前不会加载。代理拦截方法调用,然后将对象加载到内存中并将方法调用委托给它。
这是延迟加载实现的示例:
public abstract class LazilyLoadedObject implements InvocationHandler {
private Object target;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (target == null) {
target = loadObject();
}
return method.invoke(target, args);
}
/**
* Loads the proxied object. This might be an expensive operation
* or loading lots of objects could consume a lot of memory, so
* we only load the object when it's needed.
*/
protected abstract Object loadObject();
}
以上InvocationHandler
将被传递给代理,以便代理上调用的方法将由InvocationHandler
. 处理程序检查对象是否已加载。如果没有,它将调用loadObject()
,这可能是某种检索对象的数据库查询。
代理非常强大,因为它们允许拦截方法调用。AOP 中就是这种情况。