Created
July 17, 2013 02:12
-
-
Save dwelch2344/6017134 to your computer and use it in GitHub Desktop.
Some inheritable Spring containers for experimenting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import javax.servlet.ServletConfig; | |
| import javax.servlet.ServletContext; | |
| import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; | |
| import org.springframework.context.ApplicationContext; | |
| import org.springframework.context.support.AbstractRefreshableConfigApplicationContext; | |
| import org.springframework.core.env.ConfigurableEnvironment; | |
| import org.springframework.core.io.Resource; | |
| import org.springframework.core.io.support.ResourcePatternResolver; | |
| import org.springframework.ui.context.Theme; | |
| import org.springframework.ui.context.ThemeSource; | |
| import org.springframework.ui.context.support.UiApplicationContextUtils; | |
| import org.springframework.web.context.ConfigurableWebApplicationContext; | |
| import org.springframework.web.context.ConfigurableWebEnvironment; | |
| import org.springframework.web.context.ServletConfigAware; | |
| import org.springframework.web.context.ServletContextAware; | |
| import org.springframework.web.context.support.ServletContextAwareProcessor; | |
| import org.springframework.web.context.support.ServletContextResource; | |
| import org.springframework.web.context.support.ServletContextResourcePatternResolver; | |
| import org.springframework.web.context.support.StandardServletEnvironment; | |
| import org.springframework.web.context.support.WebApplicationContextUtils; | |
| import org.springframework.web.context.support.XmlWebApplicationContext; | |
| /** | |
| * {@link org.springframework.context.support.AbstractRefreshableApplicationContext} | |
| * subclass which implements the | |
| * {@link org.springframework.web.context.ConfigurableWebApplicationContext} | |
| * interface for web environments. Provides a "configLocations" property, | |
| * to be populated through the ConfigurableWebApplicationContext interface | |
| * on web application startup. | |
| * | |
| * <p>This class is as easy to subclass as AbstractRefreshableApplicationContext: | |
| * All you need to implements is the {@link #loadBeanDefinitions} method; | |
| * see the superclass javadoc for details. Note that implementations are supposed | |
| * to load bean definitions from the files specified by the locations returned | |
| * by the {@link #getConfigLocations} method. | |
| * | |
| * <p>Interprets resource paths as servlet context resources, i.e. as paths beneath | |
| * the web application root. Absolute paths, e.g. for files outside the web app root, | |
| * can be accessed via "file:" URLs, as implemented by | |
| * {@link org.springframework.core.io.DefaultResourceLoader}. | |
| * | |
| * <p>In addition to the special beans detected by | |
| * {@link org.springframework.context.support.AbstractApplicationContext}, | |
| * this class detects a bean of type {@link org.springframework.ui.context.ThemeSource} | |
| * in the context, under the special bean name "themeSource". | |
| * | |
| * <p><b>This is the web context to be subclassed for a different bean definition format.</b> | |
| * Such a context implementation can be specified as "contextClass" context-param | |
| * for {@link org.springframework.web.context.ContextLoader} or as "contextClass" | |
| * init-param for {@link org.springframework.web.servlet.FrameworkServlet}, | |
| * replacing the default {@link XmlWebApplicationContext}. It will then automatically | |
| * receive the "contextConfigLocation" context-param or init-param, respectively. | |
| * | |
| * <p>Note that WebApplicationContext implementations are generally supposed | |
| * to configure themselves based on the configuration received through the | |
| * {@link ConfigurableWebApplicationContext} interface. In contrast, a standalone | |
| * application context might allow for configuration in custom startup code | |
| * (for example, {@link org.springframework.context.support.GenericApplicationContext}). | |
| * | |
| * @author Juergen Hoeller | |
| * @since 1.1.3 | |
| * @see #loadBeanDefinitions | |
| * @see org.springframework.web.context.ConfigurableWebApplicationContext#setConfigLocations | |
| * @see org.springframework.ui.context.ThemeSource | |
| * @see XmlWebApplicationContext | |
| */ | |
| public abstract class InheritableAbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext | |
| implements ConfigurableWebApplicationContext, ThemeSource { | |
| /** Servlet context that this context runs in */ | |
| private ServletContext servletContext; | |
| /** Servlet config that this context runs in, if any */ | |
| private ServletConfig servletConfig; | |
| /** Namespace of this context, or {@code null} if root */ | |
| private String namespace; | |
| /** the ThemeSource for this ApplicationContext */ | |
| private ThemeSource themeSource; | |
| public InheritableAbstractRefreshableWebApplicationContext() { | |
| setDisplayName("Root WebApplicationContext"); | |
| } | |
| public InheritableAbstractRefreshableWebApplicationContext(ApplicationContext parentCtx) { | |
| super(parentCtx); | |
| setDisplayName("Root WebApplicationContext"); | |
| } | |
| public void setServletContext(ServletContext servletContext) { | |
| this.servletContext = servletContext; | |
| } | |
| public ServletContext getServletContext() { | |
| return this.servletContext; | |
| } | |
| public void setServletConfig(ServletConfig servletConfig) { | |
| this.servletConfig = servletConfig; | |
| if (servletConfig != null && this.servletContext == null) { | |
| setServletContext(servletConfig.getServletContext()); | |
| } | |
| } | |
| public ServletConfig getServletConfig() { | |
| return this.servletConfig; | |
| } | |
| public void setNamespace(String namespace) { | |
| this.namespace = namespace; | |
| if (namespace != null) { | |
| setDisplayName("WebApplicationContext for namespace '" + namespace + "'"); | |
| } | |
| } | |
| public String getNamespace() { | |
| return this.namespace; | |
| } | |
| @Override | |
| public String[] getConfigLocations() { | |
| return super.getConfigLocations(); | |
| } | |
| @Override | |
| public String getApplicationName() { | |
| if (this.servletContext == null) { | |
| return ""; | |
| } | |
| if (this.servletContext.getMajorVersion() == 2 && this.servletContext.getMinorVersion() < 5) { | |
| String name = this.servletContext.getServletContextName(); | |
| return (name != null ? name : ""); | |
| } | |
| else { | |
| // Servlet 2.5 available | |
| return this.servletContext.getContextPath(); | |
| } | |
| } | |
| /** | |
| * Create and return a new {@link StandardServletEnvironment}. Subclasses may override | |
| * in order to configure the environment or specialize the environment type returned. | |
| */ | |
| @Override | |
| protected ConfigurableEnvironment createEnvironment() { | |
| return new StandardServletEnvironment(); | |
| } | |
| /** | |
| * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc. | |
| */ | |
| @Override | |
| protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { | |
| beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); | |
| beanFactory.ignoreDependencyInterface(ServletContextAware.class); | |
| beanFactory.ignoreDependencyInterface(ServletConfigAware.class); | |
| WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); | |
| WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); | |
| } | |
| /** | |
| * This implementation supports file paths beneath the root of the ServletContext. | |
| * @see ServletContextResource | |
| */ | |
| @Override | |
| protected Resource getResourceByPath(String path) { | |
| return new ServletContextResource(this.servletContext, path); | |
| } | |
| /** | |
| * This implementation supports pattern matching in unexpanded WARs too. | |
| * @see ServletContextResourcePatternResolver | |
| */ | |
| @Override | |
| protected ResourcePatternResolver getResourcePatternResolver() { | |
| return new ServletContextResourcePatternResolver(this); | |
| } | |
| /** | |
| * Initialize the theme capability. | |
| */ | |
| @Override | |
| protected void onRefresh() { | |
| this.themeSource = UiApplicationContextUtils.initThemeSource(this); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * <p>Replace {@code Servlet}-related property sources. | |
| */ | |
| @Override | |
| protected void initPropertySources() { | |
| super.initPropertySources(); | |
| ConfigurableEnvironment env = this.getEnvironment(); | |
| if (env instanceof ConfigurableWebEnvironment) { | |
| ((ConfigurableWebEnvironment)env).initPropertySources( | |
| this.servletContext, this.servletConfig); | |
| } | |
| } | |
| public Theme getTheme(String themeName) { | |
| return this.themeSource.getTheme(themeName); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import org.springframework.beans.factory.support.BeanNameGenerator; | |
| import org.springframework.beans.factory.support.DefaultListableBeanFactory; | |
| import org.springframework.context.ApplicationContext; | |
| import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; | |
| import org.springframework.context.annotation.AnnotationConfigUtils; | |
| import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; | |
| import org.springframework.context.annotation.ScopeMetadataResolver; | |
| import org.springframework.util.Assert; | |
| import org.springframework.util.ObjectUtils; | |
| import org.springframework.util.StringUtils; | |
| import org.springframework.web.context.ContextLoader; | |
| import org.springframework.web.context.support.XmlWebApplicationContext; | |
| /** | |
| * {@link org.springframework.web.context.WebApplicationContext WebApplicationContext} | |
| * implementation which accepts annotated classes as input - in particular | |
| * {@link org.springframework.context.annotation.Configuration @Configuration}-annotated | |
| * classes, but also plain {@link org.springframework.stereotype.Component @Component} | |
| * classes and JSR-330 compliant classes using {@code javax.inject} annotations. Allows | |
| * for registering classes one by one (specifying class names as config location) as well | |
| * as for classpath scanning (specifying base packages as config location). | |
| * | |
| * <p>This is essentially the equivalent of | |
| * {@link org.springframework.context.annotation.AnnotationConfigApplicationContext | |
| * AnnotationConfigApplicationContext} for a web environment. | |
| * | |
| * <p>To make use of this application context, the | |
| * {@linkplain ContextLoader#CONTEXT_CLASS_PARAM "contextClass"} context-param for | |
| * ContextLoader and/or "contextClass" init-param for FrameworkServlet must be set to | |
| * the fully-qualified name of this class. | |
| * | |
| * <p>As of Spring 3.1, this class may also be directly instantiated and injected into | |
| * Spring's {@code DispatcherServlet} or {@code ContextLoaderListener} when using the | |
| * new {@link org.springframework.web.WebApplicationInitializer WebApplicationInitializer} | |
| * code-based alternative to {@code web.xml}. See its Javadoc for details and usage examples. | |
| * | |
| * <p>Unlike {@link XmlWebApplicationContext}, no default configuration class locations | |
| * are assumed. Rather, it is a requirement to set the | |
| * {@linkplain ContextLoader#CONFIG_LOCATION_PARAM "contextConfigLocation"} | |
| * context-param for {@link ContextLoader} and/or "contextConfigLocation" init-param for | |
| * FrameworkServlet. The param-value may contain both fully-qualified | |
| * class names and base packages to scan for components. See {@link #loadBeanDefinitions} | |
| * for exact details on how these locations are processed. | |
| * | |
| * <p>As an alternative to setting the "contextConfigLocation" parameter, users may | |
| * implement an {@link org.springframework.context.ApplicationContextInitializer | |
| * ApplicationContextInitializer} and set the | |
| * {@linkplain ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM "contextInitializerClasses"} | |
| * context-param / init-param. In such cases, users should favor the {@link #refresh()} | |
| * and {@link #scan(String...)} methods over the {@link #setConfigLocation(String)} | |
| * method, which is primarily for use by {@code ContextLoader} | |
| * | |
| * <p>Note: In case of multiple {@code @Configuration} classes, later {@code @Bean} | |
| * definitions will override ones defined in earlier loaded files. This can be leveraged | |
| * to deliberately override certain bean definitions via an extra Configuration class. | |
| * | |
| * @author Chris Beams | |
| * @author Juergen Hoeller | |
| * @since 3.0 | |
| * @see org.springframework.context.annotation.AnnotationConfigApplicationContext | |
| */ | |
| public class InheritableAnnotationConfigWebApplicationContext extends InheritableAbstractRefreshableWebApplicationContext { | |
| private Class<?>[] annotatedClasses; | |
| private String[] basePackages; | |
| private BeanNameGenerator beanNameGenerator; | |
| private ScopeMetadataResolver scopeMetadataResolver; | |
| public InheritableAnnotationConfigWebApplicationContext() { | |
| super(); | |
| } | |
| public InheritableAnnotationConfigWebApplicationContext(ApplicationContext parent) { | |
| super(parent); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * <p>This implementation accepts delimited values in the form of fully-qualified | |
| * class names, (typically of {@code Configuration} classes) or fully-qualified | |
| * packages to scan for annotated classes. During {@link #loadBeanDefinitions}, these | |
| * locations will be processed in their given order, first attempting to load each | |
| * value as a class. If class loading fails (i.e. a {@code ClassNotFoundException} | |
| * occurs), the value is assumed to be a package and scanning is attempted. | |
| * <p>Note that this method exists primarily for compatibility with Spring's | |
| * {@link org.springframework.web.context.ContextLoader} and that if this application | |
| * context is being configured through an | |
| * {@link org.springframework.context.ApplicationContextInitializer}, use of the | |
| * {@link #register} and {@link #scan} methods are preferred. | |
| * @see #register(Class...) | |
| * @see #scan(String...) | |
| * @see #setConfigLocations(String[]) | |
| * @see #loadBeanDefinitions(DefaultListableBeanFactory) | |
| */ | |
| @Override | |
| public void setConfigLocation(String location) { | |
| super.setConfigLocation(location); | |
| } | |
| /** | |
| * {@inheritDoc} | |
| * <p>This implementation accepts individual location values as fully-qualified class | |
| * names (typically {@code @Configuration} classes) or fully-qualified packages to | |
| * scan. During {@link #loadBeanDefinitions}, these locations will be processed in | |
| * order, first attempting to load values as a class, and upon class loading failure | |
| * the value is assumed to be a package to be scanned. | |
| * <p>Note that this method exists primarily for compatibility with Spring's | |
| * {@link org.springframework.web.context.ContextLoader} and that if this application | |
| * context is being configured through an | |
| * {@link org.springframework.context.ApplicationContextInitializer}, use of the | |
| * {@link #register} and {@link #scan} methods are preferred. | |
| * @see #scan(String...) | |
| * @see #register(Class...) | |
| * @see #setConfigLocation(String) | |
| * @see #loadBeanDefinitions(DefaultListableBeanFactory) | |
| */ | |
| @Override | |
| public void setConfigLocations(String[] locations) { | |
| super.setConfigLocations(locations); | |
| } | |
| /** | |
| * Register one or more annotated classes to be processed. | |
| * Note that {@link #refresh()} must be called in order for the context to fully | |
| * process the new class. | |
| * <p>Calls to {@link #register} are idempotent; adding the same | |
| * annotated class more than once has no additional effect. | |
| * @param annotatedClasses one or more annotated classes, | |
| * e.g. {@link org.springframework.context.annotation.Configuration @Configuration} classes | |
| * @see #scan(String...) | |
| * @see #loadBeanDefinitions(DefaultListableBeanFactory) | |
| * @see #setConfigLocation(String) | |
| * @see #refresh() | |
| */ | |
| public void register(Class<?>... annotatedClasses) { | |
| Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); | |
| this.annotatedClasses = annotatedClasses; | |
| } | |
| /** | |
| * Perform a scan within the specified base packages. | |
| * Note that {@link #refresh()} must be called in order for the context to | |
| * fully process the new class. | |
| * @param basePackages the packages to check for annotated classes | |
| * @see #loadBeanDefinitions(DefaultListableBeanFactory) | |
| * @see #register(Class...) | |
| * @see #setConfigLocation(String) | |
| * @see #refresh() | |
| */ | |
| public void scan(String... basePackages) { | |
| Assert.notEmpty(basePackages, "At least one base package must be specified"); | |
| this.basePackages = basePackages; | |
| } | |
| /** | |
| * Register a {@link org.springframework.beans.factory.config.BeanDefinition} for | |
| * any classes specified by {@link #register(Class...)} and scan any packages | |
| * specified by {@link #scan(String...)}. | |
| * <p>For any values specified by {@link #setConfigLocation(String)} or | |
| * {@link #setConfigLocations(String[])}, attempt first to load each location as a | |
| * class, registering a {@code BeanDefinition} if class loading is successful, | |
| * and if class loading fails (i.e. a {@code ClassNotFoundException} is raised), | |
| * assume the value is a package and attempt to scan it for annotated classes. | |
| * <p>Enables the default set of annotation configuration post processors, such that | |
| * {@code @Autowired}, {@code @Required}, and associated annotations can be used. | |
| * <p>Configuration class bean definitions are registered with generated bean | |
| * definition names unless the {@code value} attribute is provided to the stereotype | |
| * annotation. | |
| * @see #register(Class...) | |
| * @see #scan(String...) | |
| * @see #setConfigLocation(String) | |
| * @see #setConfigLocations(String[]) | |
| * @see AnnotatedBeanDefinitionReader | |
| * @see ClassPathBeanDefinitionScanner | |
| */ | |
| @Override | |
| protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) { | |
| AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory); | |
| reader.setEnvironment(this.getEnvironment()); | |
| ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory); | |
| scanner.setEnvironment(this.getEnvironment()); | |
| BeanNameGenerator beanNameGenerator = getBeanNameGenerator(); | |
| ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver(); | |
| if (beanNameGenerator != null) { | |
| reader.setBeanNameGenerator(beanNameGenerator); | |
| scanner.setBeanNameGenerator(beanNameGenerator); | |
| beanFactory.registerSingleton( | |
| AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator); | |
| } | |
| if (scopeMetadataResolver != null) { | |
| reader.setScopeMetadataResolver(scopeMetadataResolver); | |
| scanner.setScopeMetadataResolver(scopeMetadataResolver); | |
| } | |
| if (!ObjectUtils.isEmpty(this.annotatedClasses)) { | |
| if (logger.isInfoEnabled()) { | |
| logger.info("Registering annotated classes: [" + | |
| StringUtils.arrayToCommaDelimitedString(this.annotatedClasses) + "]"); | |
| } | |
| reader.register(this.annotatedClasses); | |
| } | |
| if (!ObjectUtils.isEmpty(this.basePackages)) { | |
| if (logger.isInfoEnabled()) { | |
| logger.info("Scanning base packages: [" + | |
| StringUtils.arrayToCommaDelimitedString(this.basePackages) + "]"); | |
| } | |
| scanner.scan(this.basePackages); | |
| } | |
| String[] configLocations = getConfigLocations(); | |
| if (configLocations != null) { | |
| for (String configLocation : configLocations) { | |
| try { | |
| Class<?> clazz = getClassLoader().loadClass(configLocation); | |
| if (logger.isInfoEnabled()) { | |
| logger.info("Successfully resolved class for [" + configLocation + "]"); | |
| } | |
| reader.register(clazz); | |
| } | |
| catch (ClassNotFoundException ex) { | |
| if (logger.isDebugEnabled()) { | |
| logger.debug("Could not load class for config location [" + configLocation + | |
| "] - trying package scan. " + ex); | |
| } | |
| int count = scanner.scan(configLocation); | |
| if (logger.isInfoEnabled()) { | |
| if (count == 0) { | |
| logger.info("No annotated classes found for specified class/package [" + configLocation + "]"); | |
| } | |
| else { | |
| logger.info("Found " + count + " annotated classes in package [" + configLocation + "]"); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { | |
| this.beanNameGenerator = beanNameGenerator; | |
| } | |
| /** | |
| * Provide a custom {@link BeanNameGenerator} for use with {@link AnnotatedBeanDefinitionReader} | |
| * and/or {@link ClassPathBeanDefinitionScanner}, if any. | |
| * <p>Default is {@link org.springframework.context.annotation.AnnotationBeanNameGenerator}. | |
| * @see AnnotatedBeanDefinitionReader#setBeanNameGenerator | |
| * @see ClassPathBeanDefinitionScanner#setBeanNameGenerator | |
| */ | |
| protected BeanNameGenerator getBeanNameGenerator() { | |
| return this.beanNameGenerator; | |
| } | |
| /** | |
| * Set the {@link ScopeMetadataResolver} to use for detected bean classes. | |
| * <p>The default is an {@link org.springframework.context.annotation.AnnotationScopeMetadataResolver}. | |
| */ | |
| public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) { | |
| this.scopeMetadataResolver = scopeMetadataResolver; | |
| } | |
| /** | |
| * Provide a custom {@link ScopeMetadataResolver} for use with {@link AnnotatedBeanDefinitionReader} | |
| * and/or {@link ClassPathBeanDefinitionScanner}, if any. | |
| * <p>Default is {@link org.springframework.context.annotation.AnnotationScopeMetadataResolver}. | |
| * @see AnnotatedBeanDefinitionReader#setScopeMetadataResolver | |
| * @see ClassPathBeanDefinitionScanner#setScopeMetadataResolver | |
| */ | |
| protected ScopeMetadataResolver getScopeMetadataResolver() { | |
| return this.scopeMetadataResolver; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment