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.
- 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 isFactoryBean
, so it eventually calls FactoryBeanRegistrySupport.getObjectFromFactoryBean. This method first checks if the bean is singleton, callingMessageDigestFactoryBean.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 viaMessageDigestFactoryBean.getObject()
, cached and then returned. Since you have two factory beans referenced indigester
, 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, andMessageDigestFactoryBean.getObjectType()
is called to check whether object's type is assignable fromLifecycle
interface. Again, since you have two instances ofMessageDigestFactoryBean
, each of these methods is called twice.
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.
Now for the second question - no, you did not do anything wrong, the output you see just reflects how Spring functions internally.