我现在正在读一本用韩语写的春季书,我的英语很差。请理解。
在本书中,它表示Spring的AOP使用动态代理启动类,如果它使用接口,它使用CGLIB在不使用接口的情况下启动类。 我不清楚它是什么意思。你能帮我理解它的深层含义吗?
我不知道这个问题是不是很愚蠢。但我只是好奇THX。
答案 0 :(得分:12)
代理本质上是客户端和对象之间的中介,因此它实现了对象的非最终方法。代理接口是相对简单的,因为接口只是一个需要实现的方法列表,便于拦截方法调用。
Java中的Proxy类是一个实现运行时指定的接口列表的类。然后,代理具有与其关联的InvocationHandler,其将在代理上进行的方法调用委托给被代理的对象。它充当间接的级别,这样就不会在对象本身上调用方法,而是在其代理上调用方法。 InvocationHandler
只有一个方法需要实现:
public Object invoke(Object proxy, Method method, Object[] args)
同时,调用该方法的客户端无法区分代理及其底层对象表示,也不关心。
动态代理类而不是接口,并不是那么简单。虽然Java的Proxy
仅仅是接口或接口集的运行时实现,但是对象不具有来实现接口。因此,代理类需要字节码生成,这是cglib等库发挥作用的地方。 cglib为代理类提供支持,因为它可以动态生成字节码(即类文件),这意味着它可以在运行时以Java Proxy
可以在运行时实现接口的方式扩展类。
代理有很多用途。一种这样的用途是延迟加载。延迟加载允许仅在需要时加载对象图中的对象。而不是将它们全部加载到内存中,这可能是昂贵且资源密集的,我们可以在需要访问它们时即时加载它们,例如迭代对象集合。我们只需一次加载一小组,而不是加载整个集合。这可以通过代理来实现。代理表示延迟加载的对象。在代理上调用方法之前,不会加载可能从数据库加载的对象本身。拦截方法调用的代理然后将对象加载到内存中并将方法调用委托给它。
以下是延迟加载实现的示例:
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就属于这种情况。
答案 1 :(得分:2)
Java Dynamic Proxy是Java语言的反射元素,允许用户在运行时创建接口的代理。作为反射包的一部分,它是Java的一部分,它附带了JRE / JDK。
CGLIB是一个代码生成库,它具有在运行时扩展Java类的能力。因此,Spring利用此功能为其AOP库代理非接口。