Automatically configure beans in the context of the root and dispatch applications using a separate annotation

Let's say I created an annotation called @EnableFeauturethat imports a bean configuration class EnableFeatureConfiguration. This annotation is usually placed on top of the dispatcher configuration. Must beans, like view permissions, etc., relate to this dispatcher configuration, but a few beans do relate to the root context.

How can I define these beans without the need for another annotation? My first thought was to autowire WebApplicationContextand call context.getParentBeanFactory()beans to register, but I'm not sure if this is the best way to achieve my goal. How is this usually done?


UPDATE

To clarify the problem a bit. I am working on a project to integrate a template engine with Spring MVC. The project consists of the following categories / parts:

  • Configuration
  • Annotation, for example. EnableFeature(configuration import)
  • View
  • ViewResolver
  • Factory pattern

Logically, all class categories can exist in the context of a web application. However, the factory pattern can be used by other services (email, etc.). Services that mainly exist in the root context. So I basically ask how I can make a factory accessible to the root context in a clean way. I would like the configuration to be as small as possible. Currently, installation requires only one annotation placed on top of the dispatcher configuration class.

+4
2

, , , . , context.getParentBeanFactory() context.getParent() ApplicationContextAware ApplicationContext.

- , . , Tomcat:

  • next, DispatcherServlet .

, beans : singleton beans .

, , :

  • (). IMHO, , WebApplicationContextes . :
    • beans beans: beans
    • (, , DAO ..) , .
  • ApplicationContext , beans, , .
    • ,
    • bean bean
  • beans . , , beans beans. bean bean , , ( ), ... beans,
  • .
    • ok, bean
    • - .

, Spring, . , (1- ).

beans , ​​ , , - :

@Configuration
public class FeatureConfig implements ApplicationContextAware {
    static boolean needInit = true;

    @Override
    // Register the configuration class into parent context and refreshes all
    public void setApplicationContext(ApplicationContext ac) throws BeansException {
        AnnotationConfigWebApplicationContext parent = 
                (AnnotationConfigWebApplicationContext) ((AnnotationConfigWebApplicationContext) ac).getParent();
        if (needInit) { // ensure only one refresh
            needInit = false;
            parent.register(RootConfig.class);
            parent.refresh();
            ((AnnotationConfigWebApplicationContext) ac).refresh();
        }
    }

    @Configuration
    @Conditional(NoParentContext.class)
    // Can only be registered in root context
    public static class RootConfig {
        // configuration to be injected in root context ...
    }

    // special condition that the context is root
    public static class NoParentContext implements Condition {

        @Override
        public boolean matches(ConditionContext cc, AnnotatedTypeMetadata atm) {
            logger.debug(" {} parent {}", cc.getBeanFactory(), cc.getBeanFactory().getParentBeanFactory());
            return (cc.getBeanFactory().getParentBeanFactory() == null);
        }
    }

    // other beans or configuration that normally goes in servlet context
}

@Configuration @import(FeatureConfig.class) DispatcherServlet.

. , bean @Autowired(required=false), , , .

+3

, , , , @Configuration @EnableFeature. beans EnableFeatureConfiguration.

@Configuration
public class EnableFeatureConfiguration {

  @Bean
  public MyBean myBean() {
    return MyBean();
  }
}

EnableFeature :

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(EnableFeatureConfiguration.class)
public @interface EnableFeature {
}

. :

@Configuration
@EnableFeature
public class MySpringConfig {
}
0

All Articles