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

@@ -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;