All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opensymphony.xwork2.spring.SpringObjectFactory Maven / Gradle / Ivy

There is a newer version: 6.4.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.opensymphony.xwork2.spring;

import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.HashMap;
import java.util.Map;

/**
 * 

* Simple implementation of the ObjectFactory that makes use of Spring's application context if one has been configured, * before falling back on the default mechanism of instantiating a new class using the class name. *

* *

* In order to use this class in your application, you will need to instantiate a copy of this class and set it as XWork's ObjectFactory * before the xwork.xml file is parsed. In a servlet environment, this could be done using a ServletContextListener. *

* * @author Simon Stewart ([email protected]) */ public class SpringObjectFactory extends ObjectFactory implements ApplicationContextAware { private static final Logger LOG = LogManager.getLogger(SpringObjectFactory.class); protected ApplicationContext appContext; protected AutowireCapableBeanFactory autoWiringFactory; protected int autowireStrategy = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; private final Map classes = new HashMap<>(); private boolean useClassCache = true; private boolean alwaysRespectAutowireStrategy = false; /** * This is temporary solution, after validating can be removed * @since 2.3.18 */ @Deprecated private boolean enableAopSupport = false; public SpringObjectFactory() { } @Inject(value="applicationContextPath",required=false) public void setApplicationContextPath(String ctx) { if (ctx != null) { setApplicationContext(new ClassPathXmlApplicationContext(ctx)); } } @Inject(value = "enableAopSupport", required = false) public void setEnableAopSupport(String enableAopSupport) { this.enableAopSupport = BooleanUtils.toBoolean(enableAopSupport); } /** * Set the Spring ApplicationContext that should be used to look beans up with. * * @param appContext The Spring ApplicationContext that should be used to look beans up with. */ public void setApplicationContext(ApplicationContext appContext) throws BeansException { this.appContext = appContext; autoWiringFactory = findAutoWiringBeanFactory(this.appContext); } /** * Sets the autowiring strategy * * @param autowireStrategy the autowire strategy */ public void setAutowireStrategy(int autowireStrategy) { switch (autowireStrategy) { case AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT: LOG.info("Setting autowire strategy to autodetect"); this.autowireStrategy = autowireStrategy; break; case AutowireCapableBeanFactory.AUTOWIRE_BY_NAME: LOG.info("Setting autowire strategy to name"); this.autowireStrategy = autowireStrategy; break; case AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE: LOG.info("Setting autowire strategy to type"); this.autowireStrategy = autowireStrategy; break; case AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR: LOG.info("Setting autowire strategy to constructor"); this.autowireStrategy = autowireStrategy; break; case AutowireCapableBeanFactory.AUTOWIRE_NO: LOG.info("Setting autowire strategy to none"); this.autowireStrategy = autowireStrategy; break; default: throw new IllegalStateException("Invalid autowire type set"); } } public int getAutowireStrategy() { return autowireStrategy; } /** * If the given context is assignable to AutowireCapbleBeanFactory or contains a parent or a factory that is, then * set the autoWiringFactory appropriately. * * @param context the application context * * @return the bean factory */ protected AutowireCapableBeanFactory findAutoWiringBeanFactory(ApplicationContext context) { if (context instanceof AutowireCapableBeanFactory) { // Check the context return (AutowireCapableBeanFactory) context; } else if (context instanceof ConfigurableApplicationContext) { // Try and grab the beanFactory return ((ConfigurableApplicationContext) context).getBeanFactory(); } else if (context.getParent() != null) { // And if all else fails, try again with the parent context return findAutoWiringBeanFactory(context.getParent()); } return null; } /** * Looks up beans using Spring's application context before falling back to the method defined in the {@link * ObjectFactory}. * * @param beanName The name of the bean to look up in the application context * @param extraContext additional context parameters * @return A bean from Spring or the result of calling the overridden * method. * @throws Exception in case of any errors */ @Override public Object buildBean(String beanName, Map extraContext, boolean injectInternal) throws Exception { Object o; if (appContext.containsBean(beanName)) { o = appContext.getBean(beanName); } else { Class beanClazz = getClassInstance(beanName); o = buildBean(beanClazz, extraContext); } if (injectInternal) { injectInternalBeans(o); } return o; } /** * @param clazz class of bean * @param extraContext additional context parameters * @return bean * @throws Exception in case of any errors */ @Override public Object buildBean(Class clazz, Map 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.initializeBean(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); } } public Object autoWireBean(Object bean) { return autoWireBean(bean, autoWiringFactory); } /** * @param bean the bean to be autowired * @param autoWiringFactory the autowiring factory * * @return bean */ public Object autoWireBean(Object bean, AutowireCapableBeanFactory autoWiringFactory) { if (autoWiringFactory != null) { autoWiringFactory.autowireBeanProperties(bean, autowireStrategy, false); } injectApplicationContext(bean); injectInternalBeans(bean); return bean; } private void injectApplicationContext(Object bean) { if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(appContext); } } public Class getClassInstance(String className) throws ClassNotFoundException { Class clazz = null; if (useClassCache) { synchronized(classes) { // this cache of classes is needed because Spring sucks at dealing with situations where the // class instance changes clazz = (Class) classes.get(className); } } if (clazz == null) { if (appContext.containsBean(className)) { clazz = appContext.getBean(className).getClass(); } else { clazz = super.getClassInstance(className); } if (useClassCache) { synchronized(classes) { classes.put(className, clazz); } } } return clazz; } /** * Allows for ObjectFactory implementations that support * Actions without no-arg constructors. * * @return false */ @Override public boolean isNoArgConstructorRequired() { return false; } /** * Enable / disable caching of classes loaded by Spring. * * @param useClassCache enable / disable class cache */ public void setUseClassCache(boolean useClassCache) { this.useClassCache = useClassCache; } /** * Determines if the autowire strategy is always followed when creating beans * * @param alwaysRespectAutowireStrategy True if the strategy is always used */ public void setAlwaysRespectAutowireStrategy(boolean alwaysRespectAutowireStrategy) { this.alwaysRespectAutowireStrategy = alwaysRespectAutowireStrategy; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy