Drop outdated BeanFactoryLocator / beanRefContext.xml mechanism

Issue: SPR-15154
This commit is contained in:
Juergen Hoeller 2017-01-17 13:58:37 +01:00
parent d96738d613
commit ac6aa53031
30 changed files with 74 additions and 2388 deletions

View File

@ -439,7 +439,6 @@ project("spring-beans") {
compile(project(":spring-core"))
compile(files(project(":spring-core").cglibRepackJar))
optional("javax.inject:javax.inject:1")
optional("javax.el:javax.el-api:${elApiVersion}")
optional("org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}")
optional("org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}")
optional("org.yaml:snakeyaml:${snakeyamlVersion}")
@ -722,7 +721,6 @@ project("spring-context-indexer") {
project("spring-web") {
description = "Spring Web"
apply plugin: "groovy"
dependencies {

View File

@ -1,68 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed 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 org.springframework.beans.factory.access;
import org.springframework.beans.BeansException;
/**
* Defines a contract for the lookup, use, and release of a
* {@link org.springframework.beans.factory.BeanFactory},
* or a {@code BeanFactory} subclass such as an
* {@link org.springframework.context.ApplicationContext}.
*
* <p>Where this interface is implemented as a singleton class such as
* {@link SingletonBeanFactoryLocator}, the Spring team <strong>strongly</strong>
* suggests that it be used sparingly and with caution. By far the vast majority
* of the code inside an application is best written in a Dependency Injection
* style, where that code is served out of a
* {@code BeanFactory}/{@code ApplicationContext} container, and has
* its own dependencies supplied by the container when it is created. However,
* even such a singleton implementation sometimes has its use in the small glue
* layers of code that is sometimes needed to tie other code together. For
* example, third party code may try to construct new objects directly, without
* the ability to force it to get these objects out of a {@code BeanFactory}.
* If the object constructed by the third party code is just a small stub or
* proxy, which then uses an implementation of this class to get a
* {@code BeanFactory} from which it gets the real object, to which it
* delegates, then proper Dependency Injection has been achieved.
*
* <p>As another example, in a complex Java EE app with multiple layers, with
* each layer having its own {@code ApplicationContext} definition (in a
* hierarchy), a class like {@code SingletonBeanFactoryLocator} may be used
* to demand load these contexts.
*
* @author Colin Sampaleanu
* @see org.springframework.beans.factory.BeanFactory
* @see org.springframework.context.access.DefaultLocatorFactory
* @see org.springframework.context.ApplicationContext
*/
public interface BeanFactoryLocator {
/**
* Use the {@link org.springframework.beans.factory.BeanFactory} (or derived
* interface such as {@link org.springframework.context.ApplicationContext})
* specified by the {@code factoryKey} parameter.
* <p>The definition is possibly loaded/created as needed.
* @param factoryKey a resource name specifying which {@code BeanFactory} the
* {@code BeanFactoryLocator} must return for usage. The actual meaning of the
* resource name is specific to the implementation of {@code BeanFactoryLocator}.
* @return the {@code BeanFactory} instance, wrapped as a {@link BeanFactoryReference} object
* @throws BeansException if there is an error loading or accessing the {@code BeanFactory}
*/
BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException;
}

View File

@ -1,57 +0,0 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed 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 org.springframework.beans.factory.access;
import org.springframework.beans.factory.BeanFactory;
/**
* Used to track a reference to a {@link BeanFactory} obtained through
* a {@link BeanFactoryLocator}.
*
* <p>It is safe to call {@link #release()} multiple times, but
* {@link #getFactory()} must not be called after calling release.
*
* @author Colin Sampaleanu
* @see BeanFactoryLocator
* @see org.springframework.context.access.ContextBeanFactoryReference
*/
public interface BeanFactoryReference {
/**
* Return the {@link BeanFactory} instance held by this reference.
* @throws IllegalStateException if invoked after {@code release()} has been called
*/
BeanFactory getFactory();
/**
* Indicate that the {@link BeanFactory} instance referred to by this object is not
* needed any longer by the client code which obtained the {@link BeanFactoryReference}.
* <p>Depending on the actual implementation of {@link BeanFactoryLocator}, and
* the actual type of {@code BeanFactory}, this may possibly not actually
* do anything; alternately in the case of a 'closeable' {@code BeanFactory}
* or derived class (such as {@link org.springframework.context.ApplicationContext})
* may 'close' it, or may 'close' it once no more references remain.
* <p>In an EJB usage scenario this would normally be called from
* {@code ejbRemove()} and {@code ejbPassivate()}.
* <p>This is safe to call multiple times.
* @see BeanFactoryLocator
* @see org.springframework.context.access.ContextBeanFactoryReference
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
void release();
}

View File

@ -1,48 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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 org.springframework.beans.factory.access;
import org.springframework.beans.FatalBeanException;
/**
* Exception thrown if a bean factory could not be loaded by a bootstrap class.
*
* @author Rod Johnson
* @since 02.12.2002
*/
@SuppressWarnings("serial")
public class BootstrapException extends FatalBeanException {
/**
* Create a new BootstrapException with the specified message.
* @param msg the detail message
*/
public BootstrapException(String msg) {
super(msg);
}
/**
* Create a new BootstrapException with the specified message
* and root cause.
* @param msg the detail message
* @param cause the root cause
*/
public BootstrapException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@ -1,536 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed 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 org.springframework.beans.factory.access;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
/**
* <p>Keyed-singleton implementation of {@link BeanFactoryLocator},
* which accesses shared Spring {@link BeanFactory} instances.</p>
*
* <p>Please see the warning in BeanFactoryLocator's javadoc about appropriate usage
* of singleton style BeanFactoryLocator implementations. It is the opinion of the
* Spring team that the use of this class and similar classes is unnecessary except
* (sometimes) for a small amount of glue code. Excessive usage will lead to code
* that is more tightly coupled, and harder to modify or test.</p>
*
* <p>In this implementation, a BeanFactory is built up from one or more XML
* definition file fragments, accessed as resources. The default resource name
* searched for is 'classpath*:beanRefFactory.xml', with the Spring-standard
* 'classpath*:' prefix ensuring that if the classpath contains multiple copies
* of this file (perhaps one in each component jar) they will be combined. To
* override the default resource name, instead of using the no-arg
* {@link #getInstance()} method, use the {@link #getInstance(String selector)}
* variant, which will treat the 'selector' argument as the resource name to
* search for.</p>
*
* <p>The purpose of this 'outer' BeanFactory is to create and hold a copy of one
* or more 'inner' BeanFactory or ApplicationContext instances, and allow those
* to be obtained either directly or via an alias. As such, this class provides
* both singleton style access to one or more BeanFactories/ApplicationContexts,
* and also a level of indirection, allowing multiple pieces of code, which are
* not able to work in a Dependency Injection fashion, to refer to and use the
* same target BeanFactory/ApplicationContext instance(s), by different names.<p>
*
* <p>Consider an example application scenario:
*
* <ul>
* <li>{@code com.mycompany.myapp.util.applicationContext.xml} -
* ApplicationContext definition file which defines beans for 'util' layer.
* <li>{@code com.mycompany.myapp.dataaccess-applicationContext.xml} -
* ApplicationContext definition file which defines beans for 'data access' layer.
* Depends on the above.
* <li>{@code com.mycompany.myapp.services.applicationContext.xml} -
* ApplicationContext definition file which defines beans for 'services' layer.
* Depends on the above.
* </ul>
*
* <p>In an ideal scenario, these would be combined to create one ApplicationContext,
* or created as three hierarchical ApplicationContexts, by one piece of code
* somewhere at application startup (perhaps a Servlet filter), from which all other
* code in the application would flow, obtained as beans from the context(s). However
* when third party code enters into the picture, things can get problematic. If the
* third party code needs to create user classes, which should normally be obtained
* from a Spring BeanFactory/ApplicationContext, but can handle only newInstance()
* style object creation, then some extra work is required to actually access and
* use object from a BeanFactory/ApplicationContext. One solutions is to make the
* class created by the third party code be just a stub or proxy, which gets the
* real object from a BeanFactory/ApplicationContext, and delegates to it. However,
* it is not normally workable for the stub to create the BeanFactory on each
* use, as depending on what is inside it, that can be an expensive operation.
* Additionally, there is a fairly tight coupling between the stub and the name of
* the definition resource for the BeanFactory/ApplicationContext. This is where
* SingletonBeanFactoryLocator comes in. The stub can obtain a
* SingletonBeanFactoryLocator instance, which is effectively a singleton, and
* ask it for an appropriate BeanFactory. A subsequent invocation (assuming the
* same class loader is involved) by the stub or another piece of code, will obtain
* the same instance. The simple aliasing mechanism allows the context to be asked
* for by a name which is appropriate for (or describes) the user. The deployer can
* match alias names to actual context names.
*
* <p>Another use of SingletonBeanFactoryLocator, is to demand-load/use one or more
* BeanFactories/ApplicationContexts. Because the definition can contain one of more
* BeanFactories/ApplicationContexts, which can be independent or in a hierarchy, if
* they are set to lazy-initialize, they will only be created when actually requested
* for use.
*
* <p>Given the above-mentioned three ApplicationContexts, consider the simplest
* SingletonBeanFactoryLocator usage scenario, where there is only one single
* {@code beanRefFactory.xml} definition file:
*
* <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
* &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
*
* &lt;beans>
*
* &lt;bean id="com.mycompany.myapp"
* class="org.springframework.context.support.ClassPathXmlApplicationContext">
* &lt;constructor-arg>
* &lt;list>
* &lt;value>com/mycompany/myapp/util/applicationContext.xml&lt;/value>
* &lt;value>com/mycompany/myapp/dataaccess/applicationContext.xml&lt;/value>
* &lt;value>com/mycompany/myapp/dataaccess/services.xml&lt;/value>
* &lt;/list>
* &lt;/constructor-arg>
* &lt;/bean>
*
* &lt;/beans>
* </pre>
*
* The client code is as simple as:
*
* <pre class="code">
* BeanFactoryLocator bfl = SingletonBeanFactoryLocator.getInstance();
* BeanFactoryReference bf = bfl.useBeanFactory("com.mycompany.myapp");
* // now use some bean from factory
* MyClass zed = bf.getFactory().getBean("mybean");
* </pre>
*
* Another relatively simple variation of the {@code beanRefFactory.xml} definition file could be:
*
* <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
* &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
*
* &lt;beans>
*
* &lt;bean id="com.mycompany.myapp.util" lazy-init="true"
* class="org.springframework.context.support.ClassPathXmlApplicationContext">
* &lt;constructor-arg>
* &lt;value>com/mycompany/myapp/util/applicationContext.xml&lt;/value>
* &lt;/constructor-arg>
* &lt;/bean>
*
* &lt;!-- child of above -->
* &lt;bean id="com.mycompany.myapp.dataaccess" lazy-init="true"
* class="org.springframework.context.support.ClassPathXmlApplicationContext">
* &lt;constructor-arg>
* &lt;list>&lt;value>com/mycompany/myapp/dataaccess/applicationContext.xml&lt;/value>&lt;/list>
* &lt;/constructor-arg>
* &lt;constructor-arg>
* &lt;ref bean="com.mycompany.myapp.util"/>
* &lt;/constructor-arg>
* &lt;/bean>
*
* &lt;!-- child of above -->
* &lt;bean id="com.mycompany.myapp.services" lazy-init="true"
* class="org.springframework.context.support.ClassPathXmlApplicationContext">
* &lt;constructor-arg>
* &lt;list>&lt;value>com/mycompany/myapp/dataaccess.services.xml&lt;/value>&lt;/value>
* &lt;/constructor-arg>
* &lt;constructor-arg>
* &lt;ref bean="com.mycompany.myapp.dataaccess"/>
* &lt;/constructor-arg>
* &lt;/bean>
*
* &lt;!-- define an alias -->
* &lt;bean id="com.mycompany.myapp.mypackage"
* class="java.lang.String">
* &lt;constructor-arg>
* &lt;value>com.mycompany.myapp.services&lt;/value>
* &lt;/constructor-arg>
* &lt;/bean>
*
* &lt;/beans>
* </pre>
*
* <p>In this example, there is a hierarchy of three contexts created. The (potential)
* advantage is that if the lazy flag is set to true, a context will only be created
* if it's actually used. If there is some code that is only needed some of the time,
* this mechanism can save some resources. Additionally, an alias to the last context
* has been created. Aliases allow usage of the idiom where client code asks for a
* context with an id which represents the package or module the code is in, and the
* actual definition file(s) for the SingletonBeanFactoryLocator maps that id to
* a real context id.
*
* <p>A final example is more complex, with a {@code beanRefFactory.xml} for every module.
* All the files are automatically combined to create the final definition.
*
* <p>{@code beanRefFactory.xml} file inside jar for util module:
*
* <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
* &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
*
* &lt;beans>
* &lt;bean id="com.mycompany.myapp.util" lazy-init="true"
* class="org.springframework.context.support.ClassPathXmlApplicationContext">
* &lt;constructor-arg>
* &lt;value>com/mycompany/myapp/util/applicationContext.xml&lt;/value>
* &lt;/constructor-arg>
* &lt;/bean>
* &lt;/beans>
* </pre>
*
* {@code beanRefFactory.xml} file inside jar for data-access module:<br>
*
* <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
* &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
*
* &lt;beans>
* &lt;!-- child of util -->
* &lt;bean id="com.mycompany.myapp.dataaccess" lazy-init="true"
* class="org.springframework.context.support.ClassPathXmlApplicationContext">
* &lt;constructor-arg>
* &lt;list>&lt;value>com/mycompany/myapp/dataaccess/applicationContext.xml&lt;/value>&lt;/list>
* &lt;/constructor-arg>
* &lt;constructor-arg>
* &lt;ref bean="com.mycompany.myapp.util"/>
* &lt;/constructor-arg>
* &lt;/bean>
* &lt;/beans>
* </pre>
*
* {@code beanRefFactory.xml} file inside jar for services module:
*
* <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
* &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
*
* &lt;beans>
* &lt;!-- child of data-access -->
* &lt;bean id="com.mycompany.myapp.services" lazy-init="true"
* class="org.springframework.context.support.ClassPathXmlApplicationContext">
* &lt;constructor-arg>
* &lt;list>&lt;value>com/mycompany/myapp/dataaccess/services.xml&lt;/value>&lt;/list>
* &lt;/constructor-arg>
* &lt;constructor-arg>
* &lt;ref bean="com.mycompany.myapp.dataaccess"/>
* &lt;/constructor-arg>
* &lt;/bean>
* &lt;/beans>
* </pre>
*
* {@code beanRefFactory.xml} file inside jar for mypackage module. This doesn't
* create any of its own contexts, but allows the other ones to be referred to be
* a name known to this module:
*
* <pre class="code">&lt;?xml version="1.0" encoding="UTF-8"?>
* &lt;!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
*
* &lt;beans>
* &lt;!-- define an alias for "com.mycompany.myapp.services" -->
* &lt;alias name="com.mycompany.myapp.services" alias="com.mycompany.myapp.mypackage"/&gt;
* &lt;/beans>
* </pre>
*
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
* @see org.springframework.context.access.DefaultLocatorFactory
*/
public class SingletonBeanFactoryLocator implements BeanFactoryLocator {
private static final String DEFAULT_RESOURCE_LOCATION = "classpath*:beanRefFactory.xml";
protected static final Log logger = LogFactory.getLog(SingletonBeanFactoryLocator.class);
/** The keyed BeanFactory instances */
private static final Map<String, BeanFactoryLocator> instances = new HashMap<>();
/**
* Returns an instance which uses the default "classpath*:beanRefFactory.xml",
* as the name of the definition file(s). All resources returned by calling the
* current thread context ClassLoader's {@code getResources} method with
* this name will be combined to create a BeanFactory definition set.
* @return the corresponding BeanFactoryLocator instance
* @throws BeansException in case of factory loading failure
*/
public static BeanFactoryLocator getInstance() throws BeansException {
return getInstance(null);
}
/**
* Returns an instance which uses the specified selector, as the name of the
* definition file(s). In the case of a name with a Spring 'classpath*:' prefix,
* or with no prefix, which is treated the same, the current thread context
* ClassLoader's {@code getResources} method will be called with this value
* to get all resources having that name. These resources will then be combined to
* form a definition. In the case where the name uses a Spring 'classpath:' prefix,
* or a standard URL prefix, then only one resource file will be loaded as the
* definition.
* @param selector the name of the resource(s) which will be read and
* combined to form the definition for the BeanFactoryLocator instance.
* Any such files must form a valid BeanFactory definition.
* @return the corresponding BeanFactoryLocator instance
* @throws BeansException in case of factory loading failure
*/
public static BeanFactoryLocator getInstance(String selector) throws BeansException {
String resourceLocation = selector;
if (resourceLocation == null) {
resourceLocation = DEFAULT_RESOURCE_LOCATION;
}
// For backwards compatibility, we prepend 'classpath*:' to the selector name if there
// is no other prefix (i.e. classpath*:, classpath:, or some URL prefix.
if (!ResourcePatternUtils.isUrl(resourceLocation)) {
resourceLocation = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resourceLocation;
}
synchronized (instances) {
if (logger.isTraceEnabled()) {
logger.trace("SingletonBeanFactoryLocator.getInstance(): instances.hashCode=" +
instances.hashCode() + ", instances=" + instances);
}
BeanFactoryLocator bfl = instances.get(resourceLocation);
if (bfl == null) {
bfl = new SingletonBeanFactoryLocator(resourceLocation);
instances.put(resourceLocation, bfl);
}
return bfl;
}
}
// We map BeanFactoryGroup objects by String keys, and by the definition object.
private final Map<String, BeanFactoryGroup> bfgInstancesByKey = new HashMap<>();
private final Map<BeanFactory, BeanFactoryGroup> bfgInstancesByObj = new HashMap<>();
private final String resourceLocation;
/**
* Constructor which uses the specified name as the resource name
* of the definition file(s).
* @param resourceLocation the Spring resource location to use
* (either a URL or a "classpath:" / "classpath*:" pseudo URL)
*/
protected SingletonBeanFactoryLocator(String resourceLocation) {
this.resourceLocation = resourceLocation;
}
@Override
public BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException {
synchronized (this.bfgInstancesByKey) {
BeanFactoryGroup bfg = this.bfgInstancesByKey.get(this.resourceLocation);
if (bfg != null) {
bfg.refCount++;
}
else {
// This group definition doesn't exist, we need to try to load it.
if (logger.isTraceEnabled()) {
logger.trace("Factory group with resource name [" + this.resourceLocation +
"] requested. Creating new instance.");
}
// Create the BeanFactory but don't initialize it.
BeanFactory groupContext = createDefinition(this.resourceLocation, factoryKey);
// Record its existence now, before instantiating any singletons.
bfg = new BeanFactoryGroup();
bfg.definition = groupContext;
bfg.refCount = 1;
this.bfgInstancesByKey.put(this.resourceLocation, bfg);
this.bfgInstancesByObj.put(groupContext, bfg);
// Now initialize the BeanFactory. This may cause a re-entrant invocation
// of this method, but since we've already added the BeanFactory to our
// mappings, the next time it will be found and simply have its
// reference count incremented.
try {
initializeDefinition(groupContext);
}
catch (BeansException ex) {
this.bfgInstancesByKey.remove(this.resourceLocation);
this.bfgInstancesByObj.remove(groupContext);
throw new BootstrapException("Unable to initialize group definition. " +
"Group resource name [" + this.resourceLocation + "], factory key [" + factoryKey + "]", ex);
}
}
try {
BeanFactory beanFactory;
if (factoryKey != null) {
beanFactory = bfg.definition.getBean(factoryKey, BeanFactory.class);
}
else {
beanFactory = bfg.definition.getBean(BeanFactory.class);
}
return new CountingBeanFactoryReference(beanFactory, bfg.definition);
}
catch (BeansException ex) {
throw new BootstrapException("Unable to return specified BeanFactory instance: factory key [" +
factoryKey + "], from group with resource name [" + this.resourceLocation + "]", ex);
}
}
}
/**
* Actually creates definition in the form of a BeanFactory, given a resource name
* which supports standard Spring resource prefixes ('classpath:', 'classpath*:', etc.)
* This is split out as a separate method so that subclasses can override the actual
* type used (to be an ApplicationContext, for example).
* <p>The default implementation simply builds a
* {@link org.springframework.beans.factory.support.DefaultListableBeanFactory}
* and populates it using an
* {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
* <p>This method should not instantiate any singletons. That function is performed
* by {@link #initializeDefinition initializeDefinition()}, which should also be
* overridden if this method is.
* @param resourceLocation the resource location for this factory group
* @param factoryKey the bean name of the factory to obtain
* @return the corresponding BeanFactory reference
*/
protected BeanFactory createDefinition(String resourceLocation, String factoryKey) {
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try {
Resource[] configResources = resourcePatternResolver.getResources(resourceLocation);
if (configResources.length == 0) {
throw new FatalBeanException("Unable to find resource for specified definition. " +
"Group resource name [" + this.resourceLocation + "], factory key [" + factoryKey + "]");
}
reader.loadBeanDefinitions(configResources);
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Error accessing bean definition resource [" + this.resourceLocation + "]", ex);
}
catch (BeanDefinitionStoreException ex) {
throw new FatalBeanException("Unable to load group definition: " +
"group resource name [" + this.resourceLocation + "], factory key [" + factoryKey + "]", ex);
}
return factory;
}
/**
* Instantiate singletons and do any other normal initialization of the factory.
* Subclasses that override {@link #createDefinition createDefinition()} should
* also override this method.
* @param groupDef the factory returned by {@link #createDefinition createDefinition()}
*/
protected void initializeDefinition(BeanFactory groupDef) {
if (groupDef instanceof ConfigurableListableBeanFactory) {
((ConfigurableListableBeanFactory) groupDef).preInstantiateSingletons();
}
}
/**
* Destroy definition in separate method so subclass may work with other definition types.
* @param groupDef the factory returned by {@link #createDefinition createDefinition()}
* @param selector the resource location for this factory group
*/
protected void destroyDefinition(BeanFactory groupDef, String selector) {
if (groupDef instanceof ConfigurableBeanFactory) {
if (logger.isTraceEnabled()) {
logger.trace("Factory group with selector '" + selector +
"' being released, as there are no more references to it");
}
((ConfigurableBeanFactory) groupDef).destroySingletons();
}
}
/**
* We track BeanFactory instances with this class.
*/
private static class BeanFactoryGroup {
private BeanFactory definition;
private int refCount = 0;
}
/**
* BeanFactoryReference implementation for this locator.
*/
private class CountingBeanFactoryReference implements BeanFactoryReference {
private BeanFactory beanFactory;
private BeanFactory groupContextRef;
public CountingBeanFactoryReference(BeanFactory beanFactory, BeanFactory groupContext) {
this.beanFactory = beanFactory;
this.groupContextRef = groupContext;
}
@Override
public BeanFactory getFactory() {
return this.beanFactory;
}
// Note that it's legal to call release more than once!
@Override
public void release() throws FatalBeanException {
synchronized (bfgInstancesByKey) {
BeanFactory savedRef = this.groupContextRef;
if (savedRef != null) {
this.groupContextRef = null;
BeanFactoryGroup bfg = bfgInstancesByObj.get(savedRef);
if (bfg != null) {
bfg.refCount--;
if (bfg.refCount == 0) {
destroyDefinition(savedRef, resourceLocation);
bfgInstancesByKey.remove(resourceLocation);
bfgInstancesByObj.remove(savedRef);
}
}
else {
// This should be impossible.
logger.warn("Tried to release a SingletonBeanFactoryLocator group definition " +
"more times than it has actually been used. Resource name [" + resourceLocation + "]");
}
}
}
}
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed 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 org.springframework.beans.factory.access.el;
import javax.el.ELContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.util.Assert;
/**
* Simple concrete variant of {@link SpringBeanELResolver}, delegating
* to a given {@link BeanFactory} that the resolver was constructed with.
*
* @author Juergen Hoeller
* @since 2.5.2
*/
public class SimpleSpringBeanELResolver extends SpringBeanELResolver {
private final BeanFactory beanFactory;
/**
* Create a new SimpleSpringBeanELResolver for the given BeanFactory.
* @param beanFactory the Spring BeanFactory to delegate to
*/
public SimpleSpringBeanELResolver(BeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
}
@Override
protected BeanFactory getBeanFactory(ELContext elContext) {
return this.beanFactory;
}
}

View File

@ -1,122 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* Licensed 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 org.springframework.beans.factory.access.el;
import java.beans.FeatureDescriptor;
import java.util.Iterator;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.PropertyNotWritableException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanFactory;
/**
* Unified EL {@code ELResolver} that delegates to a Spring BeanFactory,
* resolving name references to Spring-defined beans.
*
* @author Juergen Hoeller
* @since 2.5.2
* @see org.springframework.web.jsf.el.SpringBeanFacesELResolver
*/
public abstract class SpringBeanELResolver extends ELResolver {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@Override
public Object getValue(ELContext elContext, Object base, Object property) throws ELException {
if (base == null) {
String beanName = property.toString();
BeanFactory bf = getBeanFactory(elContext);
if (bf.containsBean(beanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Successfully resolved variable '" + beanName + "' in Spring BeanFactory");
}
elContext.setPropertyResolved(true);
return bf.getBean(beanName);
}
}
return null;
}
@Override
public Class<?> getType(ELContext elContext, Object base, Object property) throws ELException {
if (base == null) {
String beanName = property.toString();
BeanFactory bf = getBeanFactory(elContext);
if (bf.containsBean(beanName)) {
elContext.setPropertyResolved(true);
return bf.getType(beanName);
}
}
return null;
}
@Override
public void setValue(ELContext elContext, Object base, Object property, Object value) throws ELException {
if (base == null) {
String beanName = property.toString();
BeanFactory bf = getBeanFactory(elContext);
if (bf.containsBean(beanName)) {
if (value == bf.getBean(beanName)) {
// Setting the bean reference to the same value is alright - can simply be ignored...
elContext.setPropertyResolved(true);
}
else {
throw new PropertyNotWritableException(
"Variable '" + beanName + "' refers to a Spring bean which by definition is not writable");
}
}
}
}
@Override
public boolean isReadOnly(ELContext elContext, Object base, Object property) throws ELException {
if (base == null) {
String beanName = property.toString();
BeanFactory bf = getBeanFactory(elContext);
if (bf.containsBean(beanName)) {
return true;
}
}
return false;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext elContext, Object base) {
return null;
}
@Override
public Class<?> getCommonPropertyType(ELContext elContext, Object base) {
return Object.class;
}
/**
* Retrieve the Spring BeanFactory to delegate bean name resolution to.
* @param elContext the current ELContext
* @return the Spring BeanFactory (never {@code null})
*/
protected abstract BeanFactory getBeanFactory(ELContext elContext);
}

View File

@ -1,4 +0,0 @@
/**
* Support classes for accessing a Spring BeanFactory from Unified EL.
*/
package org.springframework.beans.factory.access.el;

View File

@ -1,8 +0,0 @@
/**
* Helper infrastructure to locate and access bean factories.
*
* <p><b>Note: This package is only relevant for special sharing of bean
* factories, for example behind EJB facades. It is <i>not</i> used in a
* typical web application or standalone application.</b>
*/
package org.springframework.beans.factory.access;

View File

@ -1,241 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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 org.springframework.beans.factory.access;
import java.util.List;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.util.ClassUtils;
import static org.junit.Assert.*;
/**
* Unit tests for {@link SingletonBeanFactoryLocator}.
*
* @author Colin Sampaleanu
* @author Chris Beams
*/
public class SingletonBeanFactoryLocatorTests {
private static final Class<?> CLASS = SingletonBeanFactoryLocatorTests.class;
private static final String REF1_XML = CLASS.getSimpleName() + "-ref1.xml";
@Test
public void testBasicFunctionality() {
SingletonBeanFactoryLocator facLoc = new SingletonBeanFactoryLocator(
"classpath*:" + ClassUtils.addResourcePathToPackagePath(CLASS, REF1_XML));
basicFunctionalityTest(facLoc);
}
/**
* Worker method so subclass can use it too.
*/
protected void basicFunctionalityTest(SingletonBeanFactoryLocator facLoc) {
BeanFactoryReference bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
BeanFactory fac = bfr.getFactory();
BeanFactoryReference bfr2 = facLoc.useBeanFactory("another.qualified.name");
fac = bfr2.getFactory();
// verify that the same instance is returned
TestBean tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("beans1.bean1"));
tb.setName("was beans1.bean1");
BeanFactoryReference bfr3 = facLoc.useBeanFactory("another.qualified.name");
fac = bfr3.getFactory();
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("was beans1.bean1"));
BeanFactoryReference bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias");
fac = bfr4.getFactory();
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("was beans1.bean1"));
// Now verify that we can call release in any order.
// Unfortunately this doesn't validate complete release after the last one.
bfr2.release();
bfr3.release();
bfr.release();
bfr4.release();
}
/**
* This test can run multiple times, but due to static keyed lookup of the locators,
* 2nd and subsequent calls will actuall get back same locator instance. This is not
* an issue really, since the contained beanfactories will still be loaded and released.
*/
@Test
public void testGetInstance() {
// Try with and without 'classpath*:' prefix, and with 'classpath:' prefix.
BeanFactoryLocator facLoc = SingletonBeanFactoryLocator.getInstance(
ClassUtils.addResourcePathToPackagePath(CLASS, REF1_XML));
getInstanceTest1(facLoc);
facLoc = SingletonBeanFactoryLocator.getInstance(
"classpath*:/" + ClassUtils.addResourcePathToPackagePath(CLASS, REF1_XML));
getInstanceTest2(facLoc);
// This will actually get another locator instance, as the key is the resource name.
facLoc = SingletonBeanFactoryLocator.getInstance(
"classpath:" + ClassUtils.addResourcePathToPackagePath(CLASS, REF1_XML));
getInstanceTest3(facLoc);
}
/**
* Worker method so subclass can use it too
*/
protected void getInstanceTest1(BeanFactoryLocator facLoc) {
BeanFactoryReference bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
BeanFactory fac = bfr.getFactory();
BeanFactoryReference bfr2 = facLoc.useBeanFactory("another.qualified.name");
fac = bfr2.getFactory();
// verify that the same instance is returned
TestBean tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("beans1.bean1"));
tb.setName("was beans1.bean1");
BeanFactoryReference bfr3 = facLoc.useBeanFactory("another.qualified.name");
fac = bfr3.getFactory();
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("was beans1.bean1"));
BeanFactoryReference bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias");
fac = bfr4.getFactory();
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("was beans1.bean1"));
bfr.release();
bfr3.release();
bfr2.release();
bfr4.release();
}
/**
* Worker method so subclass can use it too
*/
protected void getInstanceTest2(BeanFactoryLocator facLoc) {
BeanFactoryReference bfr;
BeanFactory fac;
BeanFactoryReference bfr2;
TestBean tb;
BeanFactoryReference bfr3;
BeanFactoryReference bfr4;
bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
fac = bfr.getFactory();
bfr2 = facLoc.useBeanFactory("another.qualified.name");
fac = bfr2.getFactory();
// verify that the same instance is returned
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("beans1.bean1"));
tb.setName("was beans1.bean1");
bfr3 = facLoc.useBeanFactory("another.qualified.name");
fac = bfr3.getFactory();
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("was beans1.bean1"));
bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias");
fac = bfr4.getFactory();
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("was beans1.bean1"));
bfr.release();
bfr2.release();
bfr4.release();
bfr3.release();
}
/**
* Worker method so subclass can use it too
*/
protected void getInstanceTest3(BeanFactoryLocator facLoc) {
BeanFactoryReference bfr;
BeanFactory fac;
BeanFactoryReference bfr2;
TestBean tb;
BeanFactoryReference bfr3;
BeanFactoryReference bfr4;
bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
fac = bfr.getFactory();
bfr2 = facLoc.useBeanFactory("another.qualified.name");
fac = bfr2.getFactory();
// verify that the same instance is returned
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("beans1.bean1"));
tb.setName("was beans1.bean1");
bfr3 = facLoc.useBeanFactory("another.qualified.name");
fac = bfr3.getFactory();
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("was beans1.bean1"));
bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias");
fac = bfr4.getFactory();
tb = (TestBean) fac.getBean("beans1.bean1");
assertTrue(tb.getName().equals("was beans1.bean1"));
bfr4.release();
bfr3.release();
bfr2.release();
bfr.release();
}
}
class TestBean {
private String name;
private List<?> list;
private Object objRef;
/**
* @return Returns the name.
*/
public String getName() {
return name;
}
/**
* @param name The name to set.
*/
public void setName(String name) {
this.name = name;
}
/**
* @return Returns the list.
*/
public List<?> getList() {
return list;
}
/**
* @param list The list to set.
*/
public void setList(List<?> list) {
this.list = list;
}
/**
* @return Returns the object.
*/
public Object getObjRef() {
return objRef;
}
/**
* @param object The object to set.
*/
public void setObjRef(Object object) {
this.objRef = object;
}
}

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: beans1.xml,v 1.3 2006/08/20 19:08:40 jhoeller Exp $ -->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="beans1.bean1" class="org.springframework.beans.factory.access.TestBean">
<property name="name"><value>beans1.bean1</value></property>
</bean>
<bean id="beans1.bean2" class="org.springframework.beans.factory.access.TestBean">
<property name="name"><value>bean2</value></property>
<property name="objRef"><ref bean="beans1.bean2"/></property>
</bean>
</beans>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: beans2.xml,v 1.3 2006/08/20 19:08:40 jhoeller Exp $ -->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="beans2.bean1" class="org.springframework.beans.factory.access.TestBean">
<property name="name"><value>beans2.bean1</value></property>
</bean>
<bean id="beans2.bean2" class="org.springframework.beans.factory.access.TestBean">
<property name="name"><value>beans2.bean2</value></property>
<property name="objRef"><ref bean="beans1.bean1"/></property>
</bean>
</beans>

View File

@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<!-- We are only using one definition file for the purposes of this test, since we do not have multiple
classloaders available in the environment to allow combining multiple files of the same name, but
of course the contents within could be spread out across multiple files of the same name withing
different jars -->
<beans>
<!-- this definition could be inside one beanRefFactory.xml file -->
<bean id="a.qualified.name.of.some.sort"
class="org.springframework.beans.factory.xml.XmlBeanFactory">
<constructor-arg value="org/springframework/beans/factory/access/SingletonBeanFactoryLocatorTests-beans1.xml"/>
</bean>
<!-- while the following two could be inside another, also on the classpath,
perhaps coming from another component jar -->
<bean id="another.qualified.name"
class="org.springframework.beans.factory.xml.XmlBeanFactory">
<constructor-arg value="org/springframework/beans/factory/access/SingletonBeanFactoryLocatorTests-beans1.xml"/>
<constructor-arg ref="a.qualified.name.of.some.sort"/> <!-- parent bean factory -->
</bean>
<alias name="another.qualified.name" alias="a.qualified.name.which.is.an.alias"/>
</beans>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: beans1.xml,v 1.3 2006/08/20 19:08:40 jhoeller Exp $ -->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="beans1.bean1" class="org.springframework.beans.factory.access.TestBean">
<property name="name"><value>beans1.bean1</value></property>
</bean>
<bean id="beans1.bean2" class="org.springframework.beans.factory.access.TestBean">
<property name="name"><value>bean2</value></property>
<property name="objRef"><ref bean="beans1.bean2"/></property>
</bean>
</beans>

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: beans2.xml,v 1.3 2006/08/20 19:08:40 jhoeller Exp $ -->
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="beans2.bean1" class="org.springframework.beans.factory.access.TestBean">
<property name="name"><value>beans2.bean1</value></property>
</bean>
<bean id="beans2.bean2" class="org.springframework.beans.factory.access.TestBean">
<property name="name"><value>beans2.bean2</value></property>
<property name="objRef"><ref bean="beans1.bean1"/></property>
</bean>
</beans>

View File

@ -1,77 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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 org.springframework.context.access;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
/**
* ApplicationContext-specific implementation of BeanFactoryReference,
* wrapping a newly created ApplicationContext, closing it on release.
*
* <p>As per BeanFactoryReference contract, {@code release} may be called
* more than once, with subsequent calls not doing anything. However, calling
* {@code getFactory} after a {@code release} call will cause an exception.
*
* @author Juergen Hoeller
* @author Colin Sampaleanu
* @since 13.02.2004
* @see org.springframework.context.ConfigurableApplicationContext#close
*/
public class ContextBeanFactoryReference implements BeanFactoryReference {
private ApplicationContext applicationContext;
/**
* Create a new ContextBeanFactoryReference for the given context.
* @param applicationContext the ApplicationContext to wrap
*/
public ContextBeanFactoryReference(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public BeanFactory getFactory() {
if (this.applicationContext == null) {
throw new IllegalStateException(
"ApplicationContext owned by this BeanFactoryReference has been released");
}
return this.applicationContext;
}
@Override
public void release() {
if (this.applicationContext != null) {
ApplicationContext savedCtx;
// We don't actually guarantee thread-safety, but it's not a lot of extra work.
synchronized (this) {
savedCtx = this.applicationContext;
this.applicationContext = null;
}
if (savedCtx != null && savedCtx instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) savedCtx).close();
}
}
}
}

View File

@ -1,106 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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 org.springframework.context.access;
import javax.naming.NamingException;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.beans.factory.access.BootstrapException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jndi.JndiLocatorSupport;
import org.springframework.util.StringUtils;
/**
* BeanFactoryLocator implementation that creates the BeanFactory from one or
* more classpath locations specified in a JNDI environment variable.
*
* <p>This default implementation creates a
* {@link org.springframework.context.support.ClassPathXmlApplicationContext}.
* Subclasses may override {@link #createBeanFactory} for custom instantiation.
*
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @see #createBeanFactory
*/
public class ContextJndiBeanFactoryLocator extends JndiLocatorSupport implements BeanFactoryLocator {
/**
* Any number of these characters are considered delimiters between
* multiple bean factory config paths in a single String value.
*/
public static final String BEAN_FACTORY_PATH_DELIMITERS = ",; \t\n";
/**
* Load/use a bean factory, as specified by a factory key which is a JNDI
* address, of the form {@code java:comp/env/ejb/BeanFactoryPath}. The
* contents of this JNDI location must be a string containing one or more
* classpath resource names (separated by any of the delimiters '{@code ,; \t\n}'
* if there is more than one. The resulting BeanFactory (or ApplicationContext)
* will be created from the combined resources.
* @see #createBeanFactory
*/
@Override
public BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException {
try {
String beanFactoryPath = lookup(factoryKey, String.class);
if (logger.isTraceEnabled()) {
logger.trace("Bean factory path from JNDI environment variable [" + factoryKey +
"] is: " + beanFactoryPath);
}
String[] paths = StringUtils.tokenizeToStringArray(beanFactoryPath, BEAN_FACTORY_PATH_DELIMITERS);
return createBeanFactory(paths);
}
catch (NamingException ex) {
throw new BootstrapException("Define an environment variable [" + factoryKey + "] containing " +
"the class path locations of XML bean definition files", ex);
}
}
/**
* Create the BeanFactory instance, given an array of class path resource Strings
* which should be combined. This is split out as a separate method so that
* subclasses can override the actual BeanFactory implementation class.
* <p>Delegates to {@code createApplicationContext} by default,
* wrapping the result in a ContextBeanFactoryReference.
* @param resources an array of Strings representing classpath resource names
* @return the created BeanFactory, wrapped in a BeanFactoryReference
* (for example, a ContextBeanFactoryReference wrapping an ApplicationContext)
* @throws BeansException if factory creation failed
* @see #createApplicationContext
* @see ContextBeanFactoryReference
*/
protected BeanFactoryReference createBeanFactory(String[] resources) throws BeansException {
ApplicationContext ctx = createApplicationContext(resources);
return new ContextBeanFactoryReference(ctx);
}
/**
* Create the ApplicationContext instance, given an array of class path resource
* Strings which should be combined
* @param resources an array of Strings representing classpath resource names
* @return the created ApplicationContext
* @throws BeansException if context creation failed
*/
protected ApplicationContext createApplicationContext(String[] resources) throws BeansException {
return new ClassPathXmlApplicationContext(resources);
}
}

View File

@ -1,162 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed 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 org.springframework.context.access;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.SingletonBeanFactoryLocator;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
/**
* <p>Variant of {@link org.springframework.beans.factory.access.SingletonBeanFactoryLocator}
* which creates its internal bean factory reference as an
* {@link org.springframework.context.ApplicationContext} instead of
* SingletonBeanFactoryLocator's simple BeanFactory. For almost all usage scenarios,
* this will not make a difference, since within that ApplicationContext or BeanFactory
* you are still free to define either BeanFactory or ApplicationContext instances.
* The main reason one would need to use this class is if bean post-processing
* (or other ApplicationContext specific features are needed in the bean reference
* definition itself).
*
* <p><strong>Note:</strong> This class uses <strong>classpath*:beanRefContext.xml</strong>
* as the default resource location for the bean factory reference definition files.
* It is not possible nor legal to share definitions with SingletonBeanFactoryLocator
* at the same time.
*
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @see org.springframework.beans.factory.access.SingletonBeanFactoryLocator
* @see org.springframework.context.access.DefaultLocatorFactory
*/
public class ContextSingletonBeanFactoryLocator extends SingletonBeanFactoryLocator {
private static final String DEFAULT_RESOURCE_LOCATION = "classpath*:beanRefContext.xml";
/** The keyed singleton instances */
private static final Map<String, BeanFactoryLocator> instances = new HashMap<>();
/**
* Returns an instance which uses the default "classpath*:beanRefContext.xml", as
* the name of the definition file(s). All resources returned by the current
* thread's context class loader's {@code getResources} method with this
* name will be combined to create a definition, which is just a BeanFactory.
* @return the corresponding BeanFactoryLocator instance
* @throws BeansException in case of factory loading failure
*/
public static BeanFactoryLocator getInstance() throws BeansException {
return getInstance(null);
}
/**
* Returns an instance which uses the specified selector, as the name of the
* definition file(s). In the case of a name with a Spring "classpath*:" prefix,
* or with no prefix, which is treated the same, the current thread's context class
* loader's {@code getResources} method will be called with this value to get
* all resources having that name. These resources will then be combined to form a
* definition. In the case where the name uses a Spring "classpath:" prefix, or
* a standard URL prefix, then only one resource file will be loaded as the
* definition.
* @param selector the location of the resource(s) which will be read and
* combined to form the definition for the BeanFactoryLocator instance.
* Any such files must form a valid ApplicationContext definition.
* @return the corresponding BeanFactoryLocator instance
* @throws BeansException in case of factory loading failure
*/
public static BeanFactoryLocator getInstance(String selector) throws BeansException {
String resourceLocation = selector;
if (resourceLocation == null) {
resourceLocation = DEFAULT_RESOURCE_LOCATION;
}
// For backwards compatibility, we prepend "classpath*:" to the selector name if there
// is no other prefix (i.e. "classpath*:", "classpath:", or some URL prefix).
if (!ResourcePatternUtils.isUrl(resourceLocation)) {
resourceLocation = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resourceLocation;
}
synchronized (instances) {
if (logger.isTraceEnabled()) {
logger.trace("ContextSingletonBeanFactoryLocator.getInstance(): instances.hashCode=" +
instances.hashCode() + ", instances=" + instances);
}
BeanFactoryLocator bfl = instances.get(resourceLocation);
if (bfl == null) {
bfl = new ContextSingletonBeanFactoryLocator(resourceLocation);
instances.put(resourceLocation, bfl);
}
return bfl;
}
}
/**
* Constructor which uses the specified name as the resource name
* of the definition file(s).
* @param resourceLocation the Spring resource location to use
* (either a URL or a "classpath:" / "classpath*:" pseudo URL)
*/
protected ContextSingletonBeanFactoryLocator(String resourceLocation) {
super(resourceLocation);
}
/**
* Overrides the default method to create definition object as an ApplicationContext
* instead of the default BeanFactory. This does not affect what can actually
* be loaded by that definition.
* <p>The default implementation simply builds a
* {@link org.springframework.context.support.ClassPathXmlApplicationContext}.
*/
@Override
protected BeanFactory createDefinition(String resourceLocation, String factoryKey) {
return new ClassPathXmlApplicationContext(new String[] {resourceLocation}, false);
}
/**
* Overrides the default method to refresh the ApplicationContext, invoking
* {@link ConfigurableApplicationContext#refresh ConfigurableApplicationContext.refresh()}.
*/
@Override
protected void initializeDefinition(BeanFactory groupDef) {
if (groupDef instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) groupDef).refresh();
}
}
/**
* Overrides the default method to operate on an ApplicationContext, invoking
* {@link ConfigurableApplicationContext#refresh ConfigurableApplicationContext.close()}.
*/
@Override
protected void destroyDefinition(BeanFactory groupDef, String selector) {
if (groupDef instanceof ConfigurableApplicationContext) {
if (logger.isTraceEnabled()) {
logger.trace("Context group with selector '" + selector +
"' being released, as there are no more references to it");
}
((ConfigurableApplicationContext) groupDef).close();
}
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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 org.springframework.context.access;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.access.BeanFactoryLocator;
/**
* A factory class to get a default ContextSingletonBeanFactoryLocator instance.
*
* @author Colin Sampaleanu
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
*/
public class DefaultLocatorFactory {
/**
* Return an instance object implementing BeanFactoryLocator. This will normally
* be a singleton instance of the specific ContextSingletonBeanFactoryLocator class,
* using the default resource selector.
*/
public static BeanFactoryLocator getInstance() throws FatalBeanException {
return ContextSingletonBeanFactoryLocator.getInstance();
}
/**
* Return an instance object implementing BeanFactoryLocator. This will normally
* be a singleton instance of the specific ContextSingletonBeanFactoryLocator class,
* using the specified resource selector.
* @param selector a selector variable which provides a hint to the factory as to
* which instance to return.
*/
public static BeanFactoryLocator getInstance(String selector) throws FatalBeanException {
return ContextSingletonBeanFactoryLocator.getInstance(selector);
}
}

View File

@ -1,8 +0,0 @@
/**
* Helper infrastructure to locate and access shared application contexts.
*
* <p><b>Note: This package is only relevant for special sharing of application
* contexts, for example behind EJB facades. It is <i>not</i> used in a typical
* web application or standalone application.</b>
*/
package org.springframework.context.access;

View File

@ -1,224 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed 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 org.springframework.ejb.interceptor;
import java.util.Map;
import java.util.WeakHashMap;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.EJBException;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.interceptor.InvocationContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
/**
* EJB3-compliant interceptor class that injects Spring beans into
* fields and methods which are annotated with {@code @Autowired}.
* Performs injection after construction as well as after activation
* of a passivated bean.
*
* <p>To be applied through an {@code @Interceptors} annotation in
* the EJB Session Bean or Message-Driven Bean class, or through an
* {@code interceptor-binding} XML element in the EJB deployment descriptor.
*
* <p>Delegates to Spring's {@link AutowiredAnnotationBeanPostProcessor}
* underneath, allowing for customization of its specific settings through
* overriding the {@link #configureBeanPostProcessor} template method.
*
* <p>The actual BeanFactory to obtain Spring beans from is determined
* by the {@link #getBeanFactory} template method. The default implementation
* obtains the Spring {@link ContextSingletonBeanFactoryLocator}, initialized
* from the default resource location <strong>classpath*:beanRefContext.xml</strong>,
* and obtains the single ApplicationContext defined there.
*
* <p><b>NOTE: If you have more than one shared ApplicationContext definition available
* in your EJB class loader, you need to override the {@link #getBeanFactoryLocatorKey}
* method and provide a specific locator key for each autowired EJB.</b>
* Alternatively, override the {@link #getBeanFactory} template method and
* obtain the target factory explicitly.
*
* <p><b>WARNING: Do not define the same bean as Spring-managed bean and as
* EJB3 session bean in the same deployment unit.</b> In particular, be
* careful when using the {@code <context:component-scan>} feature
* in combination with the deployment of Spring-based EJB3 session beans:
* Make sure that the EJB3 session beans are <i>not</i> autodetected as
* Spring-managed beans as well, using appropriate package restrictions.
*
* @author Juergen Hoeller
* @since 2.5.1
* @see org.springframework.beans.factory.annotation.Autowired
* @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
* @see #getBeanFactoryLocatorKey
*/
public class SpringBeanAutowiringInterceptor {
/*
* We're keeping the BeanFactoryReference per target object in order to
* allow for using a shared interceptor instance on pooled target beans.
* This is not strictly necessary for EJB3 Session Beans and Message-Driven
* Beans, where interceptor instances get created per target bean instance.
* It simply protects against future usage of the interceptor in a shared scenario.
*/
private final Map<Object, BeanFactoryReference> beanFactoryReferences =
new WeakHashMap<>();
/**
* Autowire the target bean after construction as well as after passivation.
* @param invocationContext the EJB3 invocation context
*/
@PostConstruct
@PostActivate
public void autowireBean(InvocationContext invocationContext) {
doAutowireBean(invocationContext.getTarget());
try {
invocationContext.proceed();
}
catch (RuntimeException ex) {
doReleaseBean(invocationContext.getTarget());
throw ex;
}
catch (Error err) {
doReleaseBean(invocationContext.getTarget());
throw err;
}
catch (Exception ex) {
doReleaseBean(invocationContext.getTarget());
// Cannot declare a checked exception on WebSphere here - so we need to wrap.
throw new EJBException(ex);
}
}
/**
* Actually autowire the target bean after construction/passivation.
* @param target the target bean to autowire
*/
protected void doAutowireBean(Object target) {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
configureBeanPostProcessor(bpp, target);
bpp.setBeanFactory(getBeanFactory(target));
bpp.processInjection(target);
}
/**
* Template method for configuring the
* {@link AutowiredAnnotationBeanPostProcessor} used for autowiring.
* @param processor the AutowiredAnnotationBeanPostProcessor to configure
* @param target the target bean to autowire with this processor
*/
protected void configureBeanPostProcessor(AutowiredAnnotationBeanPostProcessor processor, Object target) {
}
/**
* Determine the BeanFactory for autowiring the given target bean.
* @param target the target bean to autowire
* @return the BeanFactory to use (never {@code null})
* @see #getBeanFactoryReference
*/
protected BeanFactory getBeanFactory(Object target) {
BeanFactory factory = getBeanFactoryReference(target).getFactory();
if (factory instanceof ApplicationContext) {
factory = ((ApplicationContext) factory).getAutowireCapableBeanFactory();
}
return factory;
}
/**
* Determine the BeanFactoryReference for the given target bean.
* <p>The default implementation delegates to {@link #getBeanFactoryLocator}
* and {@link #getBeanFactoryLocatorKey}.
* @param target the target bean to autowire
* @return the BeanFactoryReference to use (never {@code null})
* @see #getBeanFactoryLocator
* @see #getBeanFactoryLocatorKey
* @see org.springframework.beans.factory.access.BeanFactoryLocator#useBeanFactory(String)
*/
protected BeanFactoryReference getBeanFactoryReference(Object target) {
String key = getBeanFactoryLocatorKey(target);
BeanFactoryReference ref = getBeanFactoryLocator(target).useBeanFactory(key);
this.beanFactoryReferences.put(target, ref);
return ref;
}
/**
* Determine the BeanFactoryLocator to obtain the BeanFactoryReference from.
* <p>The default implementation exposes Spring's default
* {@link ContextSingletonBeanFactoryLocator}.
* @param target the target bean to autowire
* @return the BeanFactoryLocator to use (never {@code null})
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator#getInstance()
*/
protected BeanFactoryLocator getBeanFactoryLocator(Object target) {
return ContextSingletonBeanFactoryLocator.getInstance();
}
/**
* Determine the BeanFactoryLocator key to use. This typically indicates
* the bean name of the ApplicationContext definition in
* <strong>classpath*:beanRefContext.xml</strong> resource files.
* <p>The default is {@code null}, indicating the single
* ApplicationContext defined in the locator. This must be overridden
* if more than one shared ApplicationContext definition is available.
* @param target the target bean to autowire
* @return the BeanFactoryLocator key to use (or {@code null} for
* referring to the single ApplicationContext defined in the locator)
*/
protected String getBeanFactoryLocatorKey(Object target) {
return null;
}
/**
* Release the factory which has been used for autowiring the target bean.
* @param invocationContext the EJB3 invocation context
*/
@PreDestroy
@PrePassivate
public void releaseBean(InvocationContext invocationContext) {
doReleaseBean(invocationContext.getTarget());
try {
invocationContext.proceed();
}
catch (RuntimeException ex) {
throw ex;
}
catch (Exception ex) {
// Cannot declare a checked exception on WebSphere here - so we need to wrap.
throw new EJBException(ex);
}
}
/**
* Actually release the BeanFactoryReference for the given target bean.
* @param target the target bean to release
*/
protected void doReleaseBean(Object target) {
BeanFactoryReference ref = this.beanFactoryReferences.remove(target);
if (ref != null) {
ref.release();
}
}
}

View File

@ -1,6 +0,0 @@
/**
* Support classes for EJB 3 Session Beans and Message-Driven Beans,
* performing injection of Spring beans through an EJB 3 interceptor
* that processes Spring's {@code @Autowired} annotation.
*/
package org.springframework.ejb.interceptor;

View File

@ -1,52 +0,0 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed 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 org.springframework.context.access;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
/**
* Unit test for {@link ContextBeanFactoryReference}
*
* @author Colin Sampaleanu
* @author Chris Beams
*/
public class ContextBeanFactoryReferenceTests {
@Test
public void testAllOperations() {
ConfigurableApplicationContext ctx = mock(ConfigurableApplicationContext.class);
ContextBeanFactoryReference bfr = new ContextBeanFactoryReference(ctx);
assertNotNull(bfr.getFactory());
bfr.release();
try {
bfr.getFactory();
}
catch (IllegalStateException e) {
// expected
}
verify(ctx).close();
}
}

View File

@ -1,173 +0,0 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed 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 org.springframework.context.access;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BootstrapException;
import org.springframework.context.ApplicationContext;
import org.springframework.tests.mock.jndi.SimpleNamingContextBuilder;
import static org.junit.Assert.*;
/**
* @author Colin Sampaleanu
* @author Chris Beams
*/
public class ContextJndiBeanFactoryLocatorTests {
private static final String BEAN_FACTORY_PATH_ENVIRONMENT_KEY = "java:comp/env/ejb/BeanFactoryPath";
private static final Class<?> CLASS = ContextJndiBeanFactoryLocatorTests.class;
private static final String CLASSNAME = CLASS.getSimpleName();
private static final String FQ_PATH = "/org/springframework/context/access/";
private static final String COLLECTIONS_CONTEXT = FQ_PATH + CLASSNAME + "-collections.xml";
private static final String PARENT_CONTEXT = FQ_PATH + CLASSNAME + "-parent.xml";
@Test
public void beanFactoryPathRequiredFromJndiEnvironment() throws Exception {
// Set up initial context but don't bind anything
SimpleNamingContextBuilder.emptyActivatedContextBuilder();
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
try {
jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
fail();
}
catch (BootstrapException ex) {
// Check for helpful JNDI message
assertTrue(ex.getMessage().indexOf(BEAN_FACTORY_PATH_ENVIRONMENT_KEY) != -1);
}
}
@Test
public void beanFactoryPathFromJndiEnvironmentNotFound() throws Exception {
SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
String bogusPath = "RUBBISH/com/xxxx/framework/server/test1.xml";
// Set up initial context
sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, bogusPath);
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
try {
jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
fail();
}
catch (BeansException ex) {
// Check for helpful JNDI message
assertTrue(ex.getMessage().indexOf(bogusPath) != -1);
}
}
@Test
public void beanFactoryPathFromJndiEnvironmentNotValidXml() throws Exception {
SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
String nonXmlPath = "com/xxxx/framework/server/SlsbEndpointBean.class";
// Set up initial context
sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, nonXmlPath);
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
try {
jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY);
fail();
}
catch (BeansException ex) {
// Check for helpful JNDI message
assertTrue(ex.getMessage().indexOf(nonXmlPath) != -1);
}
}
@Test
public void beanFactoryPathFromJndiEnvironmentWithSingleFile() throws Exception {
SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
// Set up initial context
sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, COLLECTIONS_CONTEXT);
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
BeanFactory bf = jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY).getFactory();
assertTrue(bf.containsBean("rod"));
assertTrue(bf instanceof ApplicationContext);
}
@Test
public void beanFactoryPathFromJndiEnvironmentWithMultipleFiles() throws Exception {
SimpleNamingContextBuilder sncb = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
String path = String.format("%s %s", COLLECTIONS_CONTEXT, PARENT_CONTEXT);
// Set up initial context
sncb.bind(BEAN_FACTORY_PATH_ENVIRONMENT_KEY, path);
ContextJndiBeanFactoryLocator jbfl = new ContextJndiBeanFactoryLocator();
BeanFactory bf = jbfl.useBeanFactory(BEAN_FACTORY_PATH_ENVIRONMENT_KEY).getFactory();
assertTrue(bf.containsBean("rod"));
assertTrue(bf.containsBean("inheritedTestBean"));
}
}
class MapAndSet {
private Object obj;
public MapAndSet(Map<?, ?> map) {
this.obj = map;
}
public MapAndSet(Set<?> set) {
this.obj = set;
}
public Object getObject() {
return obj;
}
}
/**
* Bean that exposes a simple property that can be set
* to a mix of references and individual values.
*/
class MixedCollectionBean {
private Collection<?> jumble;
public void setJumble(Collection<?> jumble) {
this.jumble = jumble;
}
public Collection<?> getJumble() {
return jumble;
}
}

View File

@ -1,97 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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 org.springframework.context.access;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.beans.factory.access.SingletonBeanFactoryLocatorTests;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ClassUtils;
import static org.junit.Assert.*;
/**
* @author Colin Sampaleanu
* @author Juergen Hoeller
* @author Chris Beams
*/
public class ContextSingletonBeanFactoryLocatorTests extends SingletonBeanFactoryLocatorTests {
private static final Class<?> CLASS = ContextSingletonBeanFactoryLocatorTests.class;
private static final String CONTEXT = CLASS.getSimpleName() + "-context.xml";
@Test
public void testBaseBeanFactoryDefs() {
// Just test the base BeanFactory/AppContext defs we are going to work
// with in other tests.
new XmlBeanDefinitionReader(new DefaultListableBeanFactory()).loadBeanDefinitions(new ClassPathResource(
"/org/springframework/beans/factory/access/beans1.xml"));
new XmlBeanDefinitionReader(new DefaultListableBeanFactory()).loadBeanDefinitions(new ClassPathResource(
"/org/springframework/beans/factory/access/beans2.xml"));
}
@Override
@Test
public void testBasicFunctionality() {
ContextSingletonBeanFactoryLocator facLoc = new ContextSingletonBeanFactoryLocator(
"classpath*:" + ClassUtils.addResourcePathToPackagePath(CLASS, CONTEXT));
basicFunctionalityTest(facLoc);
BeanFactoryReference bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort");
BeanFactory fac = bfr.getFactory();
assertTrue(fac instanceof ApplicationContext);
assertEquals("a.qualified.name.of.some.sort", ((ApplicationContext) fac).getId());
assertTrue(((ApplicationContext) fac).getDisplayName().contains("a.qualified.name.of.some.sort"));
BeanFactoryReference bfr2 = facLoc.useBeanFactory("another.qualified.name");
BeanFactory fac2 = bfr2.getFactory();
assertEquals("another.qualified.name", ((ApplicationContext) fac2).getId());
assertTrue(((ApplicationContext) fac2).getDisplayName().contains("another.qualified.name"));
assertTrue(fac2 instanceof ApplicationContext);
}
/**
* This test can run multiple times, but due to static keyed lookup of the locators,
* 2nd and subsequent calls will actually get back same locator instance. This is not
* really an issue, since the contained bean factories will still be loaded and released.
*/
@Override
@Test
public void testGetInstance() {
// Try with and without 'classpath*:' prefix, and with 'classpath:' prefix.
BeanFactoryLocator facLoc = ContextSingletonBeanFactoryLocator.getInstance(
ClassUtils.addResourcePathToPackagePath(CLASS, CONTEXT));
getInstanceTest1(facLoc);
facLoc = ContextSingletonBeanFactoryLocator.getInstance(
"classpath*:" + ClassUtils.addResourcePathToPackagePath(CLASS, CONTEXT));
getInstanceTest2(facLoc);
// This will actually get another locator instance, as the key is the resource name.
facLoc = ContextSingletonBeanFactoryLocator.getInstance(
"classpath:" + ClassUtils.addResourcePathToPackagePath(CLASS, CONTEXT));
getInstanceTest3(facLoc);
}
}

View File

@ -1,49 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed 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 org.springframework.context.access;
import org.junit.Test;
import static org.junit.Assert.*;
import org.springframework.beans.factory.access.BeanFactoryLocator;
/**
* @author Colin Sampaleanu
*/
public class DefaultLocatorFactoryTests {
/*
* Class to test for BeanFactoryLocator getInstance()
*/
@Test
public void getInstance() {
BeanFactoryLocator bf = DefaultLocatorFactory.getInstance();
BeanFactoryLocator bf2 = DefaultLocatorFactory.getInstance();
assertTrue(bf.equals(bf2));
}
/*
* Class to test for BeanFactoryLocator getInstance(String)
*/
@Test
public void getInstanceString() {
BeanFactoryLocator bf = DefaultLocatorFactory.getInstance("my-bean-refs.xml");
BeanFactoryLocator bf2 = DefaultLocatorFactory.getInstance("my-bean-refs.xml");
assertTrue(bf.equals(bf2));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -28,13 +28,10 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.access.BeanFactoryLocator;
import org.springframework.beans.factory.access.BeanFactoryReference;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.env.ConfigurableEnvironment;
@ -122,34 +119,6 @@ public class ContextLoader {
*/
public static final String GLOBAL_INITIALIZER_CLASSES_PARAM = "globalInitializerClasses";
/**
* Optional servlet context parameter (i.e., "{@code locatorFactorySelector}")
* used only when obtaining a parent context using the default implementation
* of {@link #loadParentContext(ServletContext servletContext)}.
* Specifies the 'selector' used in the
* {@link ContextSingletonBeanFactoryLocator#getInstance(String selector)}
* method call, which is used to obtain the BeanFactoryLocator instance from
* which the parent context is obtained.
* <p>The default is {@code classpath*:beanRefContext.xml},
* matching the default applied for the
* {@link ContextSingletonBeanFactoryLocator#getInstance()} method.
* Supplying the "parentContextKey" parameter is sufficient in this case.
*/
public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector";
/**
* Optional servlet context parameter (i.e., "{@code parentContextKey}")
* used only when obtaining a parent context using the default implementation
* of {@link #loadParentContext(ServletContext servletContext)}.
* Specifies the 'factoryKey' used in the
* {@link BeanFactoryLocator#useBeanFactory(String factoryKey)} method call,
* obtaining the parent application context from the BeanFactoryLocator instance.
* <p>Supplying this "parentContextKey" parameter is sufficient when relying
* on the default {@code classpath*:beanRefContext.xml} selector for
* candidate factory references.
*/
public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey";
/**
* Any number of these characters are considered delimiters between
* multiple values in a single init-param String value.
@ -197,12 +166,6 @@ public class ContextLoader {
*/
private WebApplicationContext context;
/**
* Holds BeanFactoryReference when loading parent factory via
* ContextSingletonBeanFactoryLocator.
*/
private BeanFactoryReference parentContextRef;
/** Actual ApplicationContextInitializer instances to apply to the context */
private final List<ApplicationContextInitializer<ConfigurableApplicationContext>> contextInitializers =
new ArrayList<>();
@ -535,34 +498,12 @@ public class ContextLoader {
* alternately to also share the same parent context that is visible to
* EJBs. For pure web applications, there is usually no need to worry about
* having a parent context to the root web application context.
* <p>The default implementation uses
* {@link org.springframework.context.access.ContextSingletonBeanFactoryLocator},
* configured via {@link #LOCATOR_FACTORY_SELECTOR_PARAM} and
* {@link #LOCATOR_FACTORY_KEY_PARAM}, to load a parent context
* which will be shared by all other users of ContextsingletonBeanFactoryLocator
* which also use the same configuration parameters.
* <p>The default implementation simply returns {@code null}, as of 5.0.
* @param servletContext current servlet context
* @return the parent application context, or {@code null} if none
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
*/
protected ApplicationContext loadParentContext(ServletContext servletContext) {
ApplicationContext parentContext = null;
String locatorFactorySelector = servletContext.getInitParameter(LOCATOR_FACTORY_SELECTOR_PARAM);
String parentContextKey = servletContext.getInitParameter(LOCATOR_FACTORY_KEY_PARAM);
if (parentContextKey != null) {
// locatorFactorySelector may be null, indicating the default "classpath*:beanRefContext.xml"
BeanFactoryLocator locator = ContextSingletonBeanFactoryLocator.getInstance(locatorFactorySelector);
Log logger = LogFactory.getLog(ContextLoader.class);
if (logger.isDebugEnabled()) {
logger.debug("Getting parent context definition: using parent context key of '" +
parentContextKey + "' with BeanFactoryLocator");
}
this.parentContextRef = locator.useBeanFactory(parentContextKey);
parentContext = (ApplicationContext) this.parentContextRef.getFactory();
}
return parentContext;
return null;
}
/**
@ -590,9 +531,6 @@ public class ContextLoader {
currentContextPerThread.remove(ccl);
}
servletContext.removeAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (this.parentContextRef != null) {
this.parentContextRef.release();
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,11 +16,14 @@
package org.springframework.web.jsf.el;
import java.beans.FeatureDescriptor;
import java.util.Iterator;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.PropertyNotWritableException;
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.access.el.SpringBeanELResolver;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.jsf.FacesContextUtils;
@ -64,18 +67,72 @@ import org.springframework.web.jsf.FacesContextUtils;
* @see WebApplicationContextFacesELResolver
* @see org.springframework.web.jsf.FacesContextUtils#getRequiredWebApplicationContext
*/
public class SpringBeanFacesELResolver extends SpringBeanELResolver {
public class SpringBeanFacesELResolver extends ELResolver {
/**
* This implementation delegates to {@link #getWebApplicationContext}.
* Can be overridden to provide an arbitrary BeanFactory reference to resolve
* against; usually, this will be a full Spring ApplicationContext.
* @param elContext the current JSF ELContext
* @return the Spring BeanFactory (never {@code null})
*/
@Override
protected BeanFactory getBeanFactory(ELContext elContext) {
return getWebApplicationContext(elContext);
public Object getValue(ELContext elContext, Object base, Object property) throws ELException {
if (base == null) {
String beanName = property.toString();
WebApplicationContext wac = getWebApplicationContext(elContext);
if (wac.containsBean(beanName)) {
elContext.setPropertyResolved(true);
return wac.getBean(beanName);
}
}
return null;
}
@Override
public Class<?> getType(ELContext elContext, Object base, Object property) throws ELException {
if (base == null) {
String beanName = property.toString();
WebApplicationContext wac = getWebApplicationContext(elContext);
if (wac.containsBean(beanName)) {
elContext.setPropertyResolved(true);
return wac.getType(beanName);
}
}
return null;
}
@Override
public void setValue(ELContext elContext, Object base, Object property, Object value) throws ELException {
if (base == null) {
String beanName = property.toString();
WebApplicationContext wac = getWebApplicationContext(elContext);
if (wac.containsBean(beanName)) {
if (value == wac.getBean(beanName)) {
// Setting the bean reference to the same value is alright - can simply be ignored...
elContext.setPropertyResolved(true);
}
else {
throw new PropertyNotWritableException(
"Variable '" + beanName + "' refers to a Spring bean which by definition is not writable");
}
}
}
}
@Override
public boolean isReadOnly(ELContext elContext, Object base, Object property) throws ELException {
if (base == null) {
String beanName = property.toString();
WebApplicationContext wac = getWebApplicationContext(elContext);
if (wac.containsBean(beanName)) {
return true;
}
}
return false;
}
@Override
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext elContext, Object base) {
return null;
}
@Override
public Class<?> getCommonPropertyType(ELContext elContext, Object base) {
return Object.class;
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -230,34 +230,6 @@ public class ContextLoaderTests {
}
}
@Test
public void testContextLoaderWithDefaultContextAndParent() throws Exception {
MockServletContext sc = new MockServletContext("");
sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
"/org/springframework/web/context/WEB-INF/applicationContext.xml "
+ "/org/springframework/web/context/WEB-INF/context-addition.xml");
sc.addInitParameter(ContextLoader.LOCATOR_FACTORY_SELECTOR_PARAM,
"classpath:org/springframework/web/context/ref1.xml");
sc.addInitParameter(ContextLoader.LOCATOR_FACTORY_KEY_PARAM, "a.qualified.name.of.some.sort");
ServletContextListener listener = new ContextLoaderListener();
ServletContextEvent event = new ServletContextEvent(sc);
listener.contextInitialized(event);
WebApplicationContext context = (WebApplicationContext) sc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
assertTrue("Correct WebApplicationContext exposed in ServletContext",
context instanceof XmlWebApplicationContext);
LifecycleBean lb = (LifecycleBean) context.getBean("lifecycle");
assertTrue("Has father", context.containsBean("father"));
assertTrue("Has rod", context.containsBean("rod"));
assertTrue("Has kerry", context.containsBean("kerry"));
assertTrue("Not destroyed", !lb.isDestroyed());
assertTrue(context.containsBean("beans1.bean1"));
assertTrue(context.isTypeMatch("beans1.bean1", org.springframework.beans.factory.access.TestBean.class));
assertTrue(context.containsBean("beans1.bean2"));
assertTrue(context.isTypeMatch("beans1.bean2", org.springframework.beans.factory.access.TestBean.class));
listener.contextDestroyed(event);
assertTrue("Destroyed", lb.isDestroyed());
}
@Test
public void testContextLoaderWithCustomContext() throws Exception {
MockServletContext sc = new MockServletContext("");

View File

@ -1641,61 +1641,11 @@ lookups simply provides consistent and more explicit EJB access configuration.
[[ejb-implementation]]
=== Using Spring's EJB implementation support classes
[[ejb-implementation-ejb3]]
==== EJB 3 injection interceptor
For EJB 3 Session Beans and Message-Driven Beans, Spring provides a convenient
interceptor that resolves Spring's `@Autowired` annotation in the EJB component
class: `org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor`. This
interceptor can be applied through an `@Interceptors` annotation in the EJB component
class, or through an `interceptor-binding` XML element in the EJB deployment descriptor.
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
public class MyFacadeEJB implements MyFacadeLocal {
// automatically injected with a matching Spring bean
@Autowired
private MyComponent myComp;
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}
----
`SpringBeanAutowiringInterceptor` by default obtains target beans from a
`ContextSingletonBeanFactoryLocator`, with the context defined in a bean definition file
named `beanRefContext.xml`. By default, a single context definition is expected, which
is obtained by type rather than by name. However, if you need to choose between multiple
context definitions, a specific locator key is required. The locator key (i.e. the name
of the context definition in `beanRefContext.xml`) can be explicitly specified either
through overriding the `getBeanFactoryLocatorKey` method in a custom
`SpringBeanAutowiringInterceptor` subclass.
Alternatively, consider overriding `SpringBeanAutowiringInterceptor`'s `getBeanFactory`
method, e.g. obtaining a shared `ApplicationContext` from a custom holder class.
[[jms]]
== JMS (Java Message Service)
[[jms-introduction]]
=== Introduction
Spring provides a JMS integration framework that simplifies the use of the JMS API much