[ 
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)

Reply via email to