春天工厂豆

编程入门 行业动态 更新时间:2024-10-13 22:20:08
本文介绍了春天工厂豆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在尝试掌握Spring的FactoryBean,并且遇到了问题.您能否在下面查看我的资料来源并回答.这是我的应用上下文:

I'm trying to grasp Spring's FactoryBean and I've had and issue. Could you please see my sources below and answer. It's my app context:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="www.springframework/schema/beans" xmlns:xsi="www.w3/2001/XMLSchema-instance" xmlns:context="www.springframework/schema/context" xsi:schemaLocation="www.springframework/schema/beans www.springframework/schema/beans/spring-beans-3.1.xsd www.springframework/schema/context www.springframework/schema/context/spring-context-3.1.xsd"> <context:annotation-config/> <bean id="SHADigest" class="com.dtoryanik.spring.factorybean.MessageDigestFactoryBean"> <property name="algorithmName"> <value>SHA1</value> </property> </bean> <bean id="defaultDigest" class="com.dtoryanik.spring.factorybean.MessageDigestFactoryBean"/> <bean id="digester" class="com.dtoryanik.spring.factorybean.MessageDigester"> <property name="messageDigest1"> <ref local="SHADigest"/> </property> <property name="messageDigest2"> <ref local="defaultDigest"/> </property> </bean> </beans>

实际上是工厂bean:

It's a factory bean actually:

public class MessageDigestFactoryBean implements FactoryBean<MessageDigest>{ private String algorithmName = "MD5"; private MessageDigest messageDigest = null; @Override public MessageDigest getObject() throws Exception { System.out.println("<> MessageDigestFactoryBean.getObject()"); return messageDigest; } @Override public Class<?> getObjectType() { System.out.println("<> MessageDigestFactoryBean.getObjectType()"); return MessageDigest.class; } @Override public boolean isSingleton() { System.out.println("<> MessageDigestFactoryBean.isSingleton()"); return true; } @PostConstruct public void postConstructHandler() throws NoSuchAlgorithmException { System.out.println("<> MessageDigestFactoryBean.postConstructHandler()"); messageDigest = MessageDigest.getInstance(algorithmName); } public void setAlgorithmName(String algorithmName) { this.algorithmName = algorithmName; } }

还有另一个类-MessageDigester,但是它对主题没有任何帮助.我有一个主方法类:

There is another class - MessageDigester but it does not do anything helpful for topic. And I have a main-method class:

public class MessageDigestDemo { public static void main(String[] args) { GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); ctx.load("classpath:app-ctx.xml"); ctx.refresh(); MessageDigester messageDigester = (MessageDigester) ctx.getBean("digester"); messageDigester.digest("Hello World!"); }

}

问题出在我的输出中.看来我有双重实例化.每个bean都会调用两次isSingleton(),getObject()方法(尽管我从工厂只检索了2个实例).为什么会发生?也许我做错了什么?

The issue is in my output. It seems I have a double instantiating. Methods isSingleton(), getObject() are called two times for each bean (although I retrieve only 2 instances from factory). Why does it occur? Maybe I do something wrong?

<> MessageDigestFactoryBean.postConstructHandler() <> MessageDigestFactoryBean.postConstructHandler() <> MessageDigestFactoryBean.isSingleton() <> MessageDigestFactoryBean.getObject() <> MessageDigestFactoryBean.isSingleton() <> MessageDigestFactoryBean.getObject() <> MessageDigestFactoryBean.isSingleton() <> MessageDigestFactoryBean.getObjectType() <> MessageDigestFactoryBean.isSingleton() <> MessageDigestFactoryBean.getObjectType()

推荐答案

我修改了您的MessageDigestFactoryBean类,使其也输出algorithmName,这将有助于清除情况.更改之后,输出为:

I've modified your MessageDigestFactoryBean class so that it outputs algorithmName as well, this will help to clear out the case. After that change, the output is:

<> MessageDigestFactoryBean.postConstructHandler() SHA1 <> MessageDigestFactoryBean.postConstructHandler() MD5 <> MessageDigestFactoryBean.isSingleton() SHA1 <> MessageDigestFactoryBean.getObject() SHA1 <> MessageDigestFactoryBean.isSingleton() MD5 <> MessageDigestFactoryBean.getObject() MD5 <> MessageDigestFactoryBean.isSingleton() SHA1 <> MessageDigestFactoryBean.getObjectType() SHA1 <> MessageDigestFactoryBean.isSingleton() MD5 <> MessageDigestFactoryBean.getObjectType() MD5

让我们尝试分析此输出.

Let's try to analyze this output.

  • 您已经声明了两个MessageDigestFactoryBean实例,因此当Spring在上下文中发现它们时,它将对其进行初始化,并在过程中调用以@PostConstruct- MessageDigestFactoryBean.postConstructHandler() 注释的方法.
  • 然后,当Spring发现digester bean时,它将尝试获取其依赖项. Spring认为依赖关系为FactoryBean,因此最终调用了 FactoryBeanRegistrySupport.getObjectFromFactoryBean .此方法首先检查Bean是否为单例,并调用 MessageDigestFactoryBean.isSingleton() .如果bean是单例的,则首先尝试从工厂bean对象缓存中获取对其的引用.由于这是第一次引用此bean,因此尚未缓存,因此可以通过 MessageDigestFactoryBean.getObject() 获得引用,然后进行缓存并返回.由于您在digester中引用了两个工厂bean,显然每个过程都会重复此过程.
  • 初始化完成后,Spring尝试发布 ContextRefreshedEvent 到生命周期处理器,因此它将在所有bean定义中搜索实现生命周期界面.基本上,Spring循环遍历上下文中定义的所有bean,检查匹配类型的单例bean(实际上还有更多检查,但我们仅对这些感兴趣).在此过程中,对于工厂bean,调用 MessageDigestFactoryBean.isSingleton() 以确定对象是否为单例,并调用 MessageDigestFactoryBean.getObjectType() 来检查是否可以从界面.同样,由于您有两个MessageDigestFactoryBean实例,因此这些方法中的每个方法都被调用两次.
  • You have declared two MessageDigestFactoryBean instances, so when Spring discovers them in context, it initializes them, and in process calls the method annotated with @PostConstruct - MessageDigestFactoryBean.postConstructHandler().
  • Then as Spring discovers digester bean, it tries to obtain it's dependencies. Spring sees that dependency is FactoryBean, so it eventually calls FactoryBeanRegistrySupport.getObjectFromFactoryBean. This method first checks if the bean is singleton, calling MessageDigestFactoryBean.isSingleton(). If the bean is singleton, it first tries to obtain reference to it from factory bean objects cache. Since this is the first time this bean is referenced, it's not yet cached, so reference is obtained via MessageDigestFactoryBean.getObject(), cached and then returned. Since you have two factory beans referenced in digester, obviously this process is repeated for each one.
  • After initialization is complete, Spring tries to publish ContextRefreshedEvent to the lifecycle processor, so it searches all bean definitions for an instance that implements Lifecycle interface. Basically Spring loops through all beans defined in context, checking for singleton bean of matching type (actually there are more checks, but we're interested only in these). In process of this, for factory bean MessageDigestFactoryBean.isSingleton() is called to determine whether object is singleton, and MessageDigestFactoryBean.getObjectType() is called to check whether object's type is assignable from Lifecycle interface. Again, since you have two instances of MessageDigestFactoryBean, each of these methods is called twice.
  • 这就是您呼叫ctx.refresh()时发生的情况.这只是俯视图,显然Spring在幕后做了很多工作,但这就是我所看到的与您的输出有关的一切.希望这能回答您的第一个问题.

    That's what happens when you call ctx.refresh(). This is just over the top look and obviously a lot more is done by Spring under the hood, but that's all I can see related to your output. Hope this answers your first question.

    第二个问题-不,您没有做错任何事情,您看到的输出仅反映了Spring在内部的功能.

    Now for the second question - no, you did not do anything wrong, the output you see just reflects how Spring functions internally.

    更多推荐

    春天工厂豆

    本文发布于:2023-11-28 13:41:38,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1642638.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:春天   工厂

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!