How do YOU implement dynamic batch loading beans?

ImportSelector introduction

ImportSelector this interface is not a springboot after some, it is in the org. Springframework. Context. The annotation under this package, as the spring – the context package version 3.1 release when you least expect them to.

Usage and Usage

It is easy to use to decide which classes can be initialized by the Spring container based on the configuration of the relevant environment to start.

Here’s an example:

A configuration related transaction TransactionManagementConfigurationSelector, its implementation is as follows:

@Override
protected String[] selectImports(AdviceMode adviceMode) {
   switch (adviceMode) {
      case PROXY:
         return new String[] {AutoProxyRegistrar.class.getName(),
               ProxyTransactionManagementConfiguration.class.getName()};
      case ASPECTJ:
         return new String[] {determineTransactionAspectClass()};
      default:
         return null; }}Copy the code

The summary usage should look like this:

  1. I’m going to define an Annotation, and that Annotation defines some properties, and it’s going to return a different class array based on those properties.
  2. In the selectImports method, we get the configuration of the corresponding Annotation and initialize different classes according to the configuration.
  3. The object that implements the ImportSelector interface should be introduced in the Annotation by @Import Annotation. This means that once the annotation is started, the object will be instantiated.

practice

For example, I have a requirement to export our logs to local or Ali cloud depending on whether the current environment is test or production.

Suppose I define two loggers: LoggerA and LoggerB, which implement the Logger interface. Let’s define an Annotation again.

The Annotation (@EnableMyLogger) definition:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import({LoggerSelector.class})
public @interface EnableMyLogger {
}
Copy the code

LoggerSelectorDefinition:

public class LoggerSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        List<String> classNames = new ArrayList<>();
        if (testEnv()) {
            classNames.add(LoggerA.class.getName());
        } else {
            classNames.add(LoggerB.class.getName());
        }
        return classNames.toArray(new String[0]);
    }

    private boolean testEnv(a) {
        return false; }}Copy the code

Config class definition:

@Configuration
@EnableMyLogger
public class SelectorConfig {}Copy the code

Test class definition:

public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = newAnnotationConfigApplicationContext(SelectorConfig.class); System.out.println(applicationContext.getBean(Logger.class)); }}Copy the code

Test results:

TestEnv () returns false. LoggerA is not injected into the container. LoggerB is injected into the container.