上一篇《学习AOP之认识一下SpringAOP》中大体的了解了代理、动态代理及SpringAop的知识。因为写的篇幅长了点所以还是再写一篇吧。接下来开始深入一点Spring aop的一些实现机制。
上篇中最后有那段代码使用了一个ProxyFactory类来完成代理的工作,从而实现了Aop的Around Advice,代码如下:
package aop.demo;
import org.springframework.aop.framework.ProxyFactory;
public class ClientCode {
public static void main(String[] args) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTarget(new SayImpl());
proxyFactory.addAdvice(new SayImplAroundAdvice());
ISay say = (ISay) proxyFactory.getProxy();
say.say();
}
}
那么接下来就聊聊ProxyFactory吧,看看它都干了些啥。
1、ProxyFactory的奥秘
继续看上面的代码只用了5行,这里面意思也非常明确,只有在第4行的时候有一个getProxy的方法并转换为ISay接口。看来代理对象的来源可以从它入手了。
public Object getProxy() {
return createAopProxy().getProxy();
}
只不过代码只有一行,调用的是一个createAopProxy()的方法返回了AopProxy类型的对象,再通过AopProxy的getProxy来获得了代理对象。
那么只好再看一下createAopProxy()是啥样子咯:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
这个方法在org.springframework.aop.framework.ProxyCreatorSupport这个类里面,ProxyFactory是继承了它的。这个类字面意思就是一个代理创建的支持类。
但是看了createAopProxy方法后又郁闷了,还有一个getAopProxyFactory(),真是一层套一层啊。当然这里还是需要从类的层次结构来看会清楚一些,只是我主要是看它是怎么生成代理对象的,设计上的事情回头再看。
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
这里看到了DefaultAopProxyFactory这个工厂类,好了,也就是它才是创建代理的真正人物。那么这里接着createAopProxy直接看代码:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface()) {
return new JdkDynamicAopProxy(config);
}
return CglibProxyFactory.createCglibProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
从这里可以看到有两种AopProxy的代理:Cglib和Jdk。它们俩的区别:
- Cglib创建代理慢但执行快而且可以代理类
- Jdk创建代理快但执行慢,只可以代理接口
顺着ClientCode这个代码肯定是用JdkDynmaicAopProxy,最终proxyFactory.getProxy()调用的是JdkDynmaicAopProxy的实例。那好就看一下JdkDynmaicAopProxy中getProxy都做了啥吧:
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
好了,这里看到了熟悉的代码,即通过Proxy.newProxyInstance生成代理对象交给调用者。Spring通过抽象工厂模式设计了两种代理方法。
2、再看看ProxyFactroyBean
但是在xml配置的时候用的并不是ProxyFactory,而是ProxyFactroyBean。有点奇怪,为什么会有两个类呢?先来看看ProxyFactoryBean:
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
哦哟,原来这家伙继承了FactoryBean
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)