我试图抓住Spring的FactoryBean并且我已经拥有并发布了。你能否在下面看看我的消息来源并回答。这是我的应用环境:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/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:
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,但它对主题没有任何帮助。我有一个主方法类:
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!");
}
}
问题出在我的输出中。看来我有双重实例化。方法isSingleton(),getObject()为每个bean调用两次(尽管我从工厂只检索了2个实例)。它为什么会发生?也许我做错了什么?
<> MessageDigestFactoryBean.postConstructHandler()
<> MessageDigestFactoryBean.postConstructHandler()
<> MessageDigestFactoryBean.isSingleton()
<> MessageDigestFactoryBean.getObject()
<> MessageDigestFactoryBean.isSingleton()
<> MessageDigestFactoryBean.getObject()
<> MessageDigestFactoryBean.isSingleton()
<> MessageDigestFactoryBean.getObjectType()
<> MessageDigestFactoryBean.isSingleton()
<> MessageDigestFactoryBean.getObjectType()
答案 0 :(得分:2)
我修改了您的MessageDigestFactoryBean
课程,以便它也输出algorithmName
,这有助于清除案例。在更改之后,输出为:
<> 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
让我们试着分析一下这个输出。
MessageDigestFactoryBean
个实例,因此当Spring在上下文中发现它们时,它会初始化它们,并在进程中调用使用@PostConstruct
注释的方法 - MessageDigestFactoryBean.postConstructHandler()
强> digester
bean时,它会尝试获取它的依赖关系。 Spring看到依赖项为FactoryBean
,因此最终会调用FactoryBeanRegistrySupport.getObjectFromFactoryBean。此方法首先检查bean是否是单例,调用 MessageDigestFactoryBean.isSingleton()
。如果bean是单例,它首先尝试从工厂bean对象缓存中获取对它的引用。由于这是第一次引用此bean,它尚未缓存,因此通过 MessageDigestFactoryBean.getObject()
获取引用,缓存然后返回。由于digester
中引用了两个工厂bean,显然每个工艺都会重复此过程。MessageDigestFactoryBean.isSingleton()
来确定对象是否为单例,并调用 MessageDigestFactoryBean.getObjectType()
来检查对象的类型是否为可从Lifecycle
接口分配。同样,由于您有两个MessageDigestFactoryBean
实例,因此每个方法都被调用两次。当你拨打ctx.refresh()
时会发生这种情况。这只是顶部的外观,显然更多的是由引擎盖完成的,但这就是我能看到的与你的输出有关的东西。希望这能回答你的第一个问题。
现在第二个问题 - 不,你没有做错任何事,你看到的输出只反映了Spring在内部的运作方式。