[
https://issues.apache.org/jira/browse/WW-4554?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14966783#comment-14966783
]
Chris Cranford commented on WW-4554:
------------------------------------
It isn't the use of the {{autoWire}} method that is a concern but rather the
use of {{initializeBean}}. Per the spring documentation:
{noformat}
/**
* Initialize the given raw bean, applying factory callbacks
* such as {@code setBeanName} and {@code setBeanFactory},
* also applying all bean post processors (including ones which
* might wrap the given raw bean).
* <p>Note that no bean definition of the given name has to exist
* in the bean factory. The passed-in bean name will simply be used
* for callbacks but not checked against the registered bean
definitions.
* @param existingBean the existing bean instance
* @param beanName the name of the bean, to be passed to it if necessary
* (only passed to {@link BeanPostProcessor BeanPostProcessors})
* @return the bean instance to use, either the original or a wrapped
one
* @throws BeansException if the initialization failed
*/
{noformat}
Inside the SpringObjectFactory you'll notice:
{noformat}
@Override
public Object buildBean(Class clazz, Map<String, Object> extraContext)
throws Exception {
Object bean;
try {
// Decide to follow autowire strategy or use the legacy approach
which mixes injection strategies
if (alwaysRespectAutowireStrategy) {
// Leave the creation up to Spring
bean = autoWiringFactory.createBean(clazz, autowireStrategy,
false);
injectApplicationContext(bean);
return injectInternalBeans(bean);
} else if (enableAopSupport) {
bean = autoWiringFactory.createBean(clazz,
AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
bean = autoWireBean(bean, autoWiringFactory);
bean = autoWiringFactory.initializeBean(bean,
bean.getClass().getName());
return bean;
} else {
bean = autoWiringFactory.autowire(clazz,
AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false);
bean =
autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean,
bean.getClass().getName());
bean = autoWiringFactory.initializeBean(bean,
bean.getClass().getName());
bean =
autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean,
bean.getClass().getName());
return autoWireBean(bean, autoWiringFactory);
}
} catch (UnsatisfiedDependencyException e) {
LOG.error("Error building bean", e);
// Fall back
return autoWireBean(super.buildBean(clazz, extraContext),
autoWiringFactory);
}
}
{noformat}
The last else-block is the issue because the {{BeanPostProcessor}}s are being
manually invoked on the autowire factory yet {{initializeBean}} specifically
does that per the documentation and has since at least Spring 3.0.5.
> Spring BeanPostProcessor(s) are called twice for Struts constructed objects.
> ----------------------------------------------------------------------------
>
> Key: WW-4554
> URL: https://issues.apache.org/jira/browse/WW-4554
> Project: Struts 2
> Issue Type: Bug
> Components: Plugin - Spring
> Affects Versions: 2.3.24
> Reporter: Chris Cranford
> Fix For: 2.3.25
>
>
> It appears that the SpringObjectFactory in the xwork core at lines 194-197
> manually yet when calling initializeBean on the autowire factory, the spring
> framework automatically invokes these processors too which lead to the
> following post processor's callbacks being invoked twice for both the before
> and after handlers.
> I confirmed that both Sprnig 3.0.5 and 4.2.1 have called the bean post
> processors when the initializeBean function is called. See a simple
> NullBeanPostProcessor implementation below that can be used as a simple test
> of post processor invocation.
> {code:title=NullBeanPostProcessor.java|borderStyle=solid}
> import org.slf4j.Logger;
> import org.slf4j.LoggerFactory;
> import org.springframework.beans.BeansException;
> import org.springframework.beans.factory.config.BeanPostProcessor;
> /**
> * @since 7.0.0
> */
> public class NullBeanPostProcessor implements BeanPostProcessor {
> private static final Logger LOGGER =
> LoggerFactory.getLogger(NullBeanPostProcessor.class);
>
> /**
> * {@inheritDoc}
> */
> @Override
> public Object postProcessBeforeInitialization(Object bean, String
> beanName)
> throws BeansException {
> LOGGER.debug("Before Initialization for {} ({})", beanName,
> bean);
> return bean;
> }
> /**
> * {@inheritDoc}
> */
> @Override
> public Object postProcessAfterInitialization(Object bean, String
> beanName)
> throws BeansException {
> LOGGER.debug("After Initialization for {} ({})", beanName,
> bean);
> return bean;
> }
> }
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)