深入理解Spring框架:AOP(2)代理类创建与ProxyFactoryBean详解

更新:10-29 名人轶事 我要投稿 纠错 投诉

大家好,如果您还对深入理解Spring框架:AOP(2)代理类创建与ProxyFactoryBean详解不太了解,没有关系,今天就由本站为大家分享深入理解Spring框架:AOP(2)代理类创建与ProxyFactoryBean详解的知识,包括的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!

在解析wrapIfNecessary之前,先看一下上图,分析一些基础类:Advised

Advised 提供建议和顾问的管理。建议建议支持

Advised的实现类,从代码中可以看到Advice会被封装成DefaultIntroductionAdvisor。公共无效addAdvice(int pos,建议advice)抛出AopConfigException {

Assert.notNull(advice, "建议不能为空");

if (IntroductionInfo 的建议实例) {

//我们不需要这种介绍的IntroductionAdvisor:

//它是完全自描述的。

addAdvisor(pos,新的DefaultIntroductionAdvisor(建议,(IntroductionInfo)建议));

}

else if (DynamicIntroductionAdvice 的建议实例) {

//我们需要一个IntroductionAdvisor来进行这种介绍。

throw new AopConfigException("DynamicIntroductionAdvice 只能作为IntroductionAdvisor 的一部分添加");

}

别的{

addAdvisor(pos, new DefaultPointcutAdvisor(advice));

}

}

private void addAdvisorInternal(int pos, Advisor Advisor) 抛出AopConfigException {

Assert.notNull(advisor, "Advisor 不能为null");

如果(isFrozen()){

throw new AopConfigException("无法添加advisor:配置已冻结。");

}

if (pos this.advisors.size()) {

抛出新的IllegalArgumentException(

"非法位置" + pos + " 在顾问列表中,大小为" + this.advisors.size());

}

this.advisors.add(pos, 顾问);

updateAdvisorArray();

建议更改();

}ProxyCreator支持

实现了AdvisedSupport,并定义了AopProxyFactory的成员变量(默认实现DefaultAopProxyFactory),因此ProxyCreatorSupport提供了通过AopProxy获取代理的能力。公共AopProxy createAopProxy(AdvisedSupport config) 抛出AopConfigException {

if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

类?targetClass=config.getTargetClass();

if (targetClass==null) {

throw new AopConfigException("TargetSource 无法确定目标类: " +

"创建代理需要接口或目标。");

}

//如果目标类有实现的接口,或者targetClass是通过Proxy(JDK代理)创建的

if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {

返回新的JdkDynamicAopProxy(config);

}

//否则通过Cglib创建动态代理

返回新的ObjenesisCglibAopProxy(config);

}

别的{

返回新的JdkDynamicAopProxy(config);

}

}代理工厂

继ProxyCreatorSupport提供了获取AopProxy的能力之后,ProxyFactory提供了通过AopProxy createAopProxy().getProxy()获取Proxy实例的能力。

ProxyFactoryProxyFactoryBean

ProxyFactoryBean不仅继承了ProxyCreatorSupport,还具有获取Proxy的能力。另外,ProxyFactoryBean还实现了FactoryBean(FactoryBean的注释,FactoryBean通过getBean()生成实例时,默认会调用getObject()来创建需要的bean。如果想要FactoryBean实例本身就需要标记),所以默认情况下会调用getObject() 方法来创建代理对象。

正确使用ProxyFactoryBean: com.gary.spring.proxy.SubjecttestAdvice //这里直接通过getBean获取ProxyFactoryBean的实例,默认会调用getObject()方法生成代理对象。

主题subject=(Subject) beanFactory.getBean("subjectProxy");

subject.sayName();这里声明了三个bean,一个真实对象RealSubject、一个Advice 和一个ProxyFactoryBean。

这三种豆子是在不同时间创建的。测试主体通过getBean() 创建subjectProxy。使用populateBean时,会创建subject对应的bean,而testAdvice则是在initializeAdvisorChain过程中通过getBean()实例化的。

ProxyFactoryBean生成Proxy代码并解析FactoryBean.getObject()代码public Object getObject() throws BeansException {

//调用initializeAdvisorChain初始化Advisor

初始化AdvisorChain();

如果(isSingleton()){

返回getSingletonInstance();

}

别的{

if (this.targetName==null) {

logger.info("对单例目标使用非单例代理通常是不可取的。" +

"通过设置"targetName"属性启用原型代理。");

}

返回newPrototypeInstance();

}

}initializeAdvisorChain 解析:

这主要涉及Advice实例的创建。如果是单例,则通过this.beanFactory.getBean(name)创建Advice实例。私有同步无效initializeAdvisorChain()抛出AopConfigException,BeansException {

//interceptorNames在xml中设置

if (!ObjectUtils.isEmpty(this.interceptorNames)) {

//所以这里我们将遍历interceptorNames并创建所需的Advisor

//根据bean 名称具体化拦截器链。

for (字符串名称: this.interceptorNames) {

//处理全局Advisor

if (name.endsWith(GLOBAL_SUFFIX)) {

if (!(ListableBeanFactory 的this.beanFactory 实例)) {

抛出新的AopConfigException(

"只能将全局顾问程序或拦截器与ListableBeanFactory 一起使用");

}

addGlobalAdvisor((ListableBeanFactory) this.beanFactory,

name.substring(0, name.length() - GLOBAL_SUFFIX.length()));

}

//处理对应的Advisor

别的{

//如果我们到达这里,我们需要添加一个命名拦截器。

//我们必须检查它是单例还是原型。

对象建议;

if (this.singleton || this.beanFactory.isSingleton(名称)) {

//将真正的Advisor/Advice 添加到链中。

//如果是单例,则通过getBane(beanName)获取Advice

建议=this.beanFactory.getBean(name);

}

别的{

//这是一个原型Advice 或Advisor: 替换为原型。

//避免仅仅为了顾问链初始化而不必要地创建原型bean。

//否则,通过属性方法创建Advisor

建议=new PrototypePlaceholderAdvisor(名称);

}

//将Advice、Advisor或对象添加到拦截器列表中

addAdvisorOnChainCreation(建议,名称);

}

}

}

this.advisorChainInitialized=true;

}创建Advice实例后,调用addAdvisorOnChainCreation将Advice转换为Advisor。

默认的AdvisorAdapterRegistry 是DefaultAdvisorAdapterRegistry。 //将Advice、Advisor或对象添加到拦截器列表中

私人无效addAdvisorOnChainCreation(对象下一个,字符串名称){

//如有必要,我们需要转换为Advisor,以便我们的源参考

//与我们从超类拦截器中找到的内容匹配。

Advisor顾问=namedBeanToAdvisor(next);

如果(logger.isTraceEnabled()) {

logger.trace("添加名称为"" + name + """ 的顾问);

}

添加顾问(顾问);

}

//通过advisorAdapterRegistry将Advice转换或包装为Advisor

私人顾问namedBeanToAdvisor(对象下一个){

尝试{

返回this.advisorAdapterRegistry.wrap(next);

}

catch (UnknownAdviceTypeException ex) {

//我们期望这是一个顾问或建议,

//但事实并非如此。这是一个配置错误。

throw new AopConfigException("未知顾问类型" + next.getClass() +

";只能在拦截器名称链中包含Advisor 或Advice 类型bean,最后一个条目除外," +

"也可能是目标或TargetSource",例如);

}

}

//将advice包装到advisor中

公共顾问包装(对象adviceObject)抛出UnknownAdviceTypeException {

//如果adviceObject是Advisor,则不包装直接返回。

if (adviceObject 顾问实例) {

返回(顾问)adviceObject;

}

//如果adviceObject不是Advice类型,则会报错,因为MethodInteceptor也是Advice的子类。

if (!(adviceObject 实例建议)) {

抛出新的UnknownAdviceTypeException(adviceObject);

}

建议advice=(建议)adviceObject;

//如果是MethodInteceptor,直接封装成DefaultPointcutAdvisor即可

if(方法拦截器的建议实例){

//众所周知,它甚至不需要适配器。

返回新的DefaultPointcutAdvisor(建议);

}

//如果是普通的Advice实现,需要使用适配器来验证Advice是否支持。

for (AdvisorAdapter 适配器: this.adapters) {

//检查是否支持。

如果(适配器.supportsAdvice(建议)){

返回新的DefaultPointcutAdvisor(建议);

}

}

抛出新的UnknownAdviceTypeException(建议);

}Advisor加载完成后,调用getSingletonInstance创建代理类。

需要注意的是,JdkDynamicAopProxy内部有一个AdvisedSupportadvised成员变量,所以在通过ProxyCreatorSupport构建JdkDynamicAopProxy时需要将其传入,因为ProxyCreatorSupport继承自AdvisedSupport。

AdvisedSupport 内部有Listadvisor,因此Advice 和Advisor 会转换为Advisor 并保存在列表内。私有同步对象getSingletonInstance() {

if (this.singletonInstance==null) {

this.targetSource=freshTargetSource();

if (this.autoDetectInterfaces getProxiedInterfaces().length==0 !isProxyTargetClass()) {

//依靠AOP 基础设施来告诉我们要代理哪些接口。

类?targetClass=getTargetClass();

if (targetClass==null) {

throw new FactoryBeanNotInitializedException("无法确定代理的目标类");

}

setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));

}

//初始化共享单例实例。

super.setFrozen(this.freezeProxy);

//调用ProxyCreatorSupport.createAopProxy()获取AopProxy,然后通过AopProxy获取Proxy实例

this.singletonInstance=getProxy(createAopProxy());

}

返回this.singletonInstance;

}

//父类ProxyCreatorSupport.createAopProxy()创建AopProxy

protected 最终同步AopProxy createAopProxy() {

if (!this.active) {

激活();

}

//注意这里传入的是这个,即AdvisedSupport实例

返回getAopProxyFactory().createAopProxy(this);

}

受保护的对象getProxy(AopProxy aopProxy) {

return aopProxy.getProxy(this.proxyClassLoader);

我们回顾一下FactoryBean的getObject流程:

普通的beanFactory.getBean("subjectProxy") 创建一个ProxyFactoryBean。在populateBean的过程中,创建了一个主题的实例。之后,调用getObjectForBeanInstance() 方法。下面是Bean和FactoryBean的区别:

受保护的对象getObjectForBeanInstance(

对象beanInstance,字符串名称,字符串beanName,@Nullable RootBeanDefinition mbd) {

//如果bean 不是工厂,不要让调用代码尝试取消引用工厂。

//isFactoryDereference会检查beanName是否以第一个开头。如果是这样,它将直接返回FactoryBean实例,而不是getObject()生成的实例。

if (BeanFactoryUtils.isFactoryDereference(名称)) {

if (beanInstance nullBean 实例) {

返回bean实例;

}

if (!(FactoryBean 的beanInstance 实例)) {

抛出新的BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());

}

}

//现在我们有了bean 实例,它可以是普通bean 也可以是FactoryBean。

//如果它是一个FactoryBean,我们用它来创建一个bean实例,除非

//调用者实际上想要一个对工厂的引用。

//如果不是FactoryBean则直接返回

//或者isFactoryDereference,即beanName为第一个,直接返回bean。

if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {

返回bean实例;

}

//如果是FactoryBean,则使用getObject()方法返回实际需要的实例对象。

对象对象=空;

if (mbd==null) {

对象=getCachedObjectForFactoryBean(beanName);

}

如果(对象==空){

//从工厂返回bean 实例。

FactoryBean?factory=(FactoryBean?) beanInstance;

//如果是单例,则缓存从FactoryBean 获取的对象。

if (mbd==null containsBeanDefinition(beanName)) {

mbd=getMergedLocalBeanDefinition(beanName);

}

布尔合成=(mbd !=null mbd.isSynthetic());

对象=getObjectFromFactoryBean(factory, beanName,synthetic);

}

关于深入理解Spring框架:AOP(2)代理类创建与ProxyFactoryBean详解到此分享完毕,希望能帮助到您。

用户评论

你身上有刺,别扎我

终于学习到spring aop 用 proxy factory bean 创建代理类了!

    有18位网友表示赞同!

高冷低能儿

之前一直不知道如何生成代理类,看了这个文章好像明白了。

    有18位网友表示赞同!

凝残月

Spring里面用ProxyFactoryBean创建代理类真是太方便了,省了好多步骤。

    有10位网友表示赞同!

陌潇潇

我还在尝试着理解 AOP 的原理,这个 ProxyFactoryBean 概念很有帮助。

    有9位网友表示赞同!

哽咽

看来以后遇到需要使用AOP的地方就不用自己写代理类了,直接用 ProxyFactoryBean就好了。

    有16位网友表示赞同!

糖果控

这个 ProxyFactoryBean 用法好像蛮灵活的,可以设置各种配置参数。

    有16位网友表示赞同!

如你所愿

最近在学习 Spring AOP 和设计模式,这个文章讲解的很透彻。

    有9位网友表示赞同!

青楼买醉

终于明白为什么说Spring 框架这么强大,就是因为这种灵活的代理机制。

    有18位网友表示赞同!

柠栀

想要使用AOP的功能,真是要感谢这个ProxyFactoryBean啊!

    有17位网友表示赞同!

半梦半醒半疯癫

学习了 ProxyFactoryBean 后,感觉自己的 Spring AOP 的理解更深刻了。

    有11位网友表示赞同!

娇眉恨

文章讲解得很好,我感觉自己对 AOP 的理解也提高了一 notch!

    有8位网友表示赞同!

心安i

希望能找到更多使用 ProxyFactoryBean 的案例,加深我的理解。

    有8位网友表示赞同!

嗯咯

ProxyFactoryBean 的强大之处在于它可以创建自定义的代理类,真是太棒了!

    有13位网友表示赞同!

苍白的笑〃

学习 Spring AOP 真是一件很有技术含量的事情!

    有11位网友表示赞同!

稳妥

这个文章让我对 ProxyFactoryBean 有了一些新的见解。

    有5位网友表示赞同!

微信名字

以后应该多学习一些关于 ProxyFactoryBean 的高级用法。

    有15位网友表示赞同!

寂莫

感觉 Spring 框架的设计思路真是太棒了,每一个组件都非常有用!!

    有6位网友表示赞同!

■□丶一切都无所谓

希望以后能有机会更加深入地了解ProxyFactoryBean的内部实现机制。

    有17位网友表示赞同!

微信名字

这个文章对我学习 Spring AOP 的帮助很大!谢谢作者!

    有16位网友表示赞同!

【深入理解Spring框架:AOP(2)代理类创建与ProxyFactoryBean详解】相关文章:

1.蛤蟆讨媳妇【哈尼族民间故事】

2.米颠拜石

3.王羲之临池学书

4.清代敢于创新的“浓墨宰相”——刘墉

5.“巧取豪夺”的由来--米芾逸事

6.荒唐洁癖 惜砚如身(米芾逸事)

7.拜石为兄--米芾逸事

8.郑板桥轶事十则

9.王献之被公主抢亲后的悲惨人生

10.史上真实张三丰:在棺材中竟神奇复活

上一篇:高考数学历年真题解析:深入剖析立体几何重难点 下一篇:淘宝双11提前抢购与当天价格对比,双十一优惠活动一览