Spring 5 Chinese parsing core – IOC container based on Java container configuration

Time:2020-11-19
1.12 based on Java container configuration

This section covers how to use annotations to configure spring containers in your Java code. It includes the following topics:

  • Basic concepts:@Beanand@Configuration
  • useAnnotationConfigApplicationContextInstantiating spring container
  • use@Beanannotation
  • use@Configurationannotation
  • Configuration combination based on Java
  • Bean definition profile
  • PropertySourceabstract
  • use@PropertySource
  • Place holder resolution
1.12.1 basic concepts: @ bean and @ configuration

The main components in spring’s new Java configuration support are@ConfigurationClass and annotation@BeanThe method of annotation.

@BeanAnnotations use to represent a method instance, configure, and instantiate new objects managed by the spring IOC container. These are similar to spring’s < beans / > XML configuration,@BeanAnnotations play the same role as the < bean / > element. You can use it@BeanAnnotation methods replace any spring@ComponentComponent. However, they are most often used with @ configuration. Annotation @ConfigurationThe annotation indicates that its main purpose is the source of the bean definition. In addition,@ConfigurationClass allows you to call other@BeanTo define the relationship between bean methods. The simplest@Configurationexample:

@Configuration
public class AppConfig {

    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

The previous AppConfig class is equivalent to the following spring < beans / > XML definition:

<beans>
    <bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>

complete@ConfigurationAnd “streamlining”@Beanpattern?

When@BeanWhen methods are declared in classes, these classes are not annotated@ConfigurationThey are referred to as “streamlined” processing. stay@ComponentOr a bean method declared in a simple old class is considered a “compact version” in which the main purpose of the class is different, and@BeanThe method has some advantages there. For example, the service component exposes the management view to the container by adding an additional @ bean method to each applicable component class. In this scenario,@BeanMethod is a general factory method mechanism.

It’s not like the whole thing@Configuration, simplify@BeanMethod cannot declare dependencies between beans. Instead, they operate on the internal state of the components they contain and (optional) parameters that may be declared. Therefore, this kind of@BeanMethod should not call other@Beanmethod. Each of these methods is actually a factory method referenced by a particular bean, without any special runtime semantics. The positive side effect here is that there is no need to apply cglib subclasses at run time, so there are no restrictions on class design (that is, the containing class may be final).

In common scenarios,@BeanMethods are declared in the @ configuration class to ensure that full mode is always used, < U > so cross method references are redirected to lifecycle management of the container < / u >. This prevents accidental calls to the same@BeanMethod, which helps to reduce subtle errors that are difficult to trace when operating in Lite mode. Note: in@ConfigurationCall others in class@BeanMethods are directed to lifecycle management of the container.

@Beanand@ConfigurationThis is discussed in depth in the following sections. First, we’ll cover various ways to create spring containers based on Java annotations.

1.12.2 by usingAnnotationConfigApplicationContextInitialize spring container

The following sections introduce spring’sAnnotationConfigApplicationContext。 This generic ApplicationContext implementation can not only receive@ConfigurationClass as input, it can also receive normal@ComponentClasses and classes annotated with jsr-330 metadata

When@ConfigurationClass is provided as input,@ConfigurationThe class itself is registered as a bean definition and all are registered in the class@BeanDeclared methods are also registered in the container as bean definitions.

When provided@ComponentAnd jsr-330 classes, they are registered as bean definitions and assume Di metadata (such as@Autowiredor@Inject)Use in these classes.

Simple construction

And instantiationClassPathXmlApplicationContextThe spring XML file is used as input in almost the same wayAnnotationConfigApplicationContextYou can change@ConfigurationClass is used as input. This allows spring containers to be used without XML at all, as shown in the following example:

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

As mentioned earlier,AnnotationConfigApplicationContextNot limited to use with @ configuration. whatever@ComponentOr jsr-330 annotated classes are supported as input constructs, similar to the following example:

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

The previous example assumes thatMyServiceImplDependency1, andDependency2Use spring dependency injection annotation, for example:@Autowired

through the use ofregister(Class<?>…)Build container for programming

You can instantiate it by using a nonparametric constructorAnnotationConfigApplicationContextAnd through the use ofregister()Method configuration. When programmatically builtAnnotationConfigApplicationContextThis method is particularly useful. How to use it is shown in the following classes:

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.register(AppConfig.class, OtherConfig.class);
    ctx.register(AdditionalConfig.class);
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
    myService.doStuff();
}

adoptscan(String…)Scan active components

Scan the active component and you can annotate your@ConfigurationClass:

@Configuration
@ComponentScan(basePackages = "com.acme") //1
public class AppConfig  {
    ...
}
  1. This annotation activates component scanning

Experienced spring users may be familiar with the equivalent XML declaration in spring context: namespace, similar to the following example:

<beans>
 <context:component-scan base-package="com.acme"/>
</beans>

In the previous example,com.acmPackets are scanned to find annotations@ComponentAnd these classes are registered in the container as spring bean definitions.AnnotationConfigApplicationContextexposescan(String…)Methods provide the same function of component scanning, similar to the following example:

public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
    ctx.scan("com.acme");
    ctx.refresh();
    MyService myService = ctx.getBean(MyService.class);
}

remember@ConfigurationClass is used to@ComponentMeta annotated, so they are candidates for component scanning. In the previous example, suppose AppConfig is declared in thecom.acmePackage (or anycom.acmeIt will call thescan()During this period, they were selected. stayrefresh()After that, all of them@BeanMethods are processed and registered as bean definitions within the container.

adoptAnnotationConfigWebApplicationContextSupport for web applications

AnnotationConfigWebApplicationContextProvidedAnnotationConfigApplicationContextOfWebApplicationContextvariant. When configuring spring’sContextLoaderListenerServlet listener, spring MVCDispatcherServletWhen you wait, you can use this implementation, belowweb.xmlFragment to configure a typical spring MVC web application (Note:contextClassusecontext-paramandinit-param):

<web-app>
1.12.3 using @ bean annotation

@BeanIs a method level annotation and a direct analogy to the XML < bean / > element. This annotation supports some properties provided through < bean / > such as init method, destroy method, autowiring

You can@Configurationand@ComponentAnnotation is used on the class@BeanNotes.

Statement bean

To declare a bean, you can annotate a method@Bean。 You use this method in theApplicationContextTo register the bean definition of a method return value of the specified type. <u> By default, the bean name is the same method name < / u >. The following example shows one@BeanMethod statement:

@Configuration
public class AppConfig {

    @Bean
    public TransferServiceImpl transferService() {
        return new TransferServiceImpl();
    }
}

The previous configuration is exactly equivalent to the following spring XML:

<beans>
    <bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

Both statements make atransferServiceThe bean ofApplicationContextAnd bind aTransferServiceImplType, similar to the following text image display:

transferService -> com.acme.TransferServiceImpl

You can also declare your@BeanMethod is an interface (or base class) return type, similar to the following example:

@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl();
    }
}

However, this limits the visibility of advanced type prediction to the specified interface type(TransferService)。 However, all types(TransferServiceImpl)In only one container, the affected singleton bean is initialized. Non lazy load singleton beans get initialized instances according to their declaration order. When other components try to match through non declared types, you may see different type matching result dependencies (for example,@Autowired TransferServiceImpl, only when instantiatedtransferServiceBean).

If you always refer to your type through the declared service interface, your@BeanReturn types can safely participate in the design decision. However, for components that implement multiple interfaces or are potentially referenced by their implementation types, it is safer to declare the most specific return type (at least as specific as the injection point that references your bean requires). Note: this means that if a component is referenced by an implementation type, the@BeanMethod, the return type is the specific implementation type.

Bean dependency

A quilt@BeanAnnotated methods can have any number of parameters that describe the dependencies needed to build the bean. For example, if ourTransferServiceYou need oneAccountRepositoryWe can implement this dependency through method parameters, such as the following example:

@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

The parsing mechanism is almost the same as constructor based dependency injection. See the more detailed sections.

Accept lifecycle callback

Any declared@BeanAnnotated classes support normal lifecycle callbacks and can use jsr-250’s@PostConstructAnd @ predestroy annotations. See the jsr-250 annotation for more details.

Regular spring lifecycle callbacks are fully supported. If the bean implementsInitializingBeanDisposableBeanorLifecycleTheir respective methods are called back by the container.

Standard set*AwareInterfaces (such as beanfactory aware, beanname aware, message source aware, applicationcontextaware, etc.) are also fully supported.

@BeanAnnotations support arbitrary initialization and destruction callback methods, which are very similar to the init method and the init method of XML < bean > element in springdestroy-methodProperty, similar to the following example:

public class BeanOne {

    public void init() {
        // initialization logic
    }
}

public class BeanTwo {

    public void cleanup() {
        // destruction logic
    }
}

@Configuration
public class AppConfig {

    @Bean(initMethod = "init")
    public BeanOne beanOne() {
        return new BeanOne();
    }

    @Bean(destroyMethod = "cleanup")
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}

By default, these beans are defined through Java configuration, and they have a commoncloseorshutdownMethod is added to the destroy callback. If you have a publiccloseorshutdownMethod and do not want to be called back when the container is closed, you should add@Bean(destroyMethod="")Go to your bean definition to disable the default(inferred)Mode.

By default, you may want to do this on resources acquired through JNDI, because their lifecycle is managed outside the application. In particular, make sure that you always do this for the data source, as this is problematic on the Java EE application server.

The following example shows how to prevent datasource from automatically destroying callbacks.

@Bean(destroyMethod="")
public DataSource dataSource() throws NamingException {
    return (DataSource) jndiTemplate.lookup("MyDS");
}

In addition, for@BeanMethod, usually using a JNDI lookup programmatically, using springJndiTemplateorJndiLocatorDelegateHelper, or use JNDI directlyInitialContextUse, not useJndiObjectFactoryBeanVariant (this forces you to declare the return type asFactoryBeanType, not the actual type. The target type, so it’s difficult to use cross reference calls in other @ bean methods that intend to reference the resources provided here.

During the construction of beanone, it is equivalent to theinit()Method, similar to the following example:

@Configuration
public class AppConfig {

    @Bean
    public BeanOne beanOne() {
        BeanOne beanOne = new BeanOne();
        beanOne.init();
        return beanOne;
    }

    // ...
}

When you work directly in Java, you can do anything with your objects without relying on the container lifecycle.

Specify bean scope

Spring includes@ScopeAnnotation, so you can use the scope of the bean.

use@Scopeannotation

You can specify that your bean definition passes through@BeanAnnotations can also specify a scope. You can use the scope in any part of the standard bean.

The default scope issingletonBut you can override this through@ScopeNote, similar to the following example:

@Configuration
public class MyConfiguration {

    @Bean
    @Scope("prototype")
    public Encryptor encryptor() {
        // ...
    }
}

@Scopeandscoped-proxy

Spring provides a convenient way to handle scope dependencies through scope proxies. When using XML configuration< aop:scoped-proxy/>Is the easiest way to create a proxy. use@ScopeAnnotations configure beans in Java, which can beproxyModeProperty provides equal support. The default is no agent(ScopedProxyMode.NO), but you can specifyScopedProxyMode.TARGET_CLASSorScopedProxyMode.INTERFACES

If you use Java, migrate the scope proxy example from the XML reference document (see scope proxy) to our@Bean, which is similar to the following:

//HTTP session scoped beans are exposed as proxies

Custom bean name

By default, the configuration class uses the@BeanMethod as the bean name. This function can be overridden by@BeanThe name attribute is similar to the following example:

@Configuration
public class AppConfig {

   @Bean(name = "myThing")
   public Thing thing() {
       return new Thing();
   }
}

Bean alias

Similar to the discussion in bean naming, sometimes giving a simple bean multiple names is also called bean alias.@BeanThe name attribute of the annotation accepts an array of strings for this alias. The following example shows how to set the alias of a bean:

@Configuration
public class AppConfig {

    @Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
    public DataSource dataSource() {
        // instantiate, configure and return DataSource bean...
    }
}

@Bean description

Sometimes it helps to provide a more detailed textual description of the bean. These beans are useful when exposed for monitoring purposes.

To add a description to@BeanYou can use@DescriptionNote, similar to the following example:

@Configuration
public class AppConfig {

    @Bean
    @Description("Provides a basic example of a bean")
    public Thing thing() {
        return new Thing();
    }
}
1.12.4 use@Configurationannotation

@ConfigurationIs a class level annotation that indicates that the object is the source of the bean definition.@ConfigurationClass declares that the bean is passed through the@BeanAnnotation method. stay@ConfigurationCall on class@BeanMethods can be used to define dependencies between beans. View the basic concepts: @ bean and @ configuration

Dependencies injected between beans

When beans depend on each other, expressing this dependency is as simple as letting one bean method call another, as shown in the following example:

@Configuration
public class AppConfig {

    @Bean
    public BeanOne beanOne() {
        return new BeanOne(beanTwo());
    }

    @Bean
    public BeanTwo beanTwo() {
        return new BeanTwo();
    }
}

In the previous example,beanOneInjecting references through constructorsbeanTwo

Only if@BeanMethod is declared in@ConfigurationClass, this method declares that the dependencies between beans are valid. You can’t do this by using the normal@ComponentDeclare dependencies between beans.

Find method injection

As mentioned earlier, lookup method injection is an advanced feature that is rarely used. It is useful in some scenarios where singleton scope beans depend on prototype scope beans. Using Java provides a natural way to implement this pattern for configuration types. The following example shows how to find method injection:

public abstract class CommandManager {
    public Object process(Object commandState) {
        // grab a new instance of the appropriate Command interface
        Command command = createCommand();
        // set the state on the (hopefully brand new) Command instance
        command.setState(commandState);
        return command.execute();
    }

    // okay... but where is the implementation of this method?
    protected abstract Command createCommand();
}

In this subclass, you can create aCommandManagerSubclass, abstractcreateCommand()Method is overridden so that it looks for a new (prototype) command object. By using java configuration. The following example shows how to do this:

@Bean
@Scope("prototype")
public AsyncCommand asyncCommand() {
    AsyncCommand command = new AsyncCommand();
    // inject dependencies here as required
    return command;
}

@Bean
public CommandManager commandManager() {
    // return new anonymous implementation of CommandManager with createCommand()
    // overridden to return a new prototype Command object
    return new CommandManager() {
        protected Command createCommand() {
            return asyncCommand();
        }
    }
}

More about how Java based configuration works internally

Consider the following example, which shows a@BeanThe annotated method is called twice.

@Configuration
public class AppConfig {

    @Bean
    public ClientService clientService1() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientService clientService2() {
        ClientServiceImpl clientService = new ClientServiceImpl();
        clientService.setClientDao(clientDao());
        return clientService;
    }

    @Bean
    public ClientDao clientDao() {
        return new ClientDaoImpl();
    }
}

clientDao()InclientService1()Called once and inclientService2()Also called once. Because this method creates a newClientDaoImplInstance and return it, you usually want to have two instances (one for each service). There must be a problem: in spring, the default instantiation bean scope issingleton。 That’s the magic: all@ConfigurationClass is a subclass of cglib at run time. In subclasses, the subclass method first checks the container cache bean before calling the parent method to create the instance.

This behavior may vary depending on your bean scope. The singleton bean we’re talking about here.

After spring 3.2, there is no need to add cglib to your classpath, because cglib classes have been repackaged inorg.springframework.cglibAnd directly contained inspring-coreJar.

Because cglib dynamically adds functionality at startup, there are some limitations. In particular, configuration classes cannot befinal。 However, after spring 4.3, any constructor is allowed on the configuration class, including@AutowiredOr constructors without default arguments declare the use of default injection.

If you want to avoid cglib restrictions, consider@ConfigurationClass (for example, a normal@Component(replace) with your@Beanmethod. stay@BeanCross method calls between methods are not intercepted, so you have to rely only on what needs to be injected at the constructor or method level.

Code example:com.liyong.ioccontainer.starter.BaseJavaConfigIocContainer

1.12.5 writing Java based configuration

Spring’s Java based configuration feature allows you to write annotations, which can reduce your configuration complexity.

Use @ import annotation

Similar to the < import / > elements are used in spring XML files to help with modular configuration,@ImportAnnotations can be loaded in other configuration classes@BeanDefinition, similar to the following example:

@Configuration
public class ConfigA {

    @Bean
    public A a() {
        return new A();
    }
}

@Configuration
@Import(ConfigA.class)
public class ConfigB {

    @Bean
    public B b() {
        return new B();
    }
}

When initializing the context, it is not necessary to specifyConfigA.classandConfigB.class, just to be provided visuallyConfigB, similar to the following example:

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);

    // now both beans A and B will be available...
    A a = ctx.getBean(A.class);
    B b = ctx.getBean(B.class);
}

This approach simplifies the instantiation of containers, and only one class needs to be handled, rather than potentially remembering a large number of them during construction@ConfigurationClass.

After spring 4.2,@ImportIt also supports reference to regular component classes, similar toAnnotationConfigApplicationContext.registermethod. This is very useful if you want to avoid component scanning by using some configuration classes as entry points to display and define all components.

In the imported@BeanInjecting dependencies into definitions

The previous example works, but it’s too simple. In most time scenarios, beans depend on each other between configuration classes. When using XML, this is not a problem, because there is no compiler involved and you can declare itref="someBean"And trust spring to handle during container initialization. When using@ConfigurationClass, the java compiler constrains on the configuration model, because references to other beans must be valid Java syntax.

Fortunately, solving this problem is very simple. As we discussed before,@BeanMethods can have any number of parameters that describe the bean’s dependencies. Consider the following more realistic scenarios for these@ConfigurationClass, each bean is defined in other classes:

@Configuration
public class ServiceConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

@Configuration
public class RepositoryConfig {

    @Bean
    public AccountRepository accountRepository(DataSource dataSource) {
        return new JdbcAccountRepository(dataSource);
    }
}

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    // everything wires up across configuration classes...
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}

There are other ways to achieve the same result. remember@ConfigurationClasses end up just another bean in the container: that means they can take advantage of@Autowiredand@ValueInjection and other features that are the same as other beans.

Make sure that dependencies injected in this way are the simplest.@ConfigurationClasses are processed very early during context initialization, and forcing dependencies to be injected in this way can result in unexpected early initialization. As shown in the example above, use parameter based injection whenever possible.

In addition, through@BeandefinitionBeanPostProcessorAnd beanfactory postprocessor. These should normally be declared asstatic @BeanMethod, do not trigger the initialization of the configuration class they contain. besides,@Autowiredand@ValueIt may not work on a configuration class because it was created as a bean instance earlier thanAutowiredAnnotationBeanPostProcessor

The following example shows how a bean can be assembled to other beans:

@Configuration
public class ServiceConfig {

    @Autowired
    private AccountRepository accountRepository;

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl(accountRepository);
    }
}

@Configuration
public class RepositoryConfig {

    private final DataSource dataSource;

    public RepositoryConfig(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Bean
    public AccountRepository accountRepository() {
        return new JdbcAccountRepository(dataSource);
    }
}

@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return new DataSource
    }
}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    // everything wires up across configuration classes...
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}

stay@ConfigurationClass construction method injection is only supported after spring 4.3. Note: if the target bean definition has only one constructor, you do not need to specify it@Autowired

Code example:com.liyong.ioccontainer.starter.BeanAndConfigurationImportContainer

Fully qualified import beans for easier navigation

In the previous scenario, use the@AutowiredIt works well and provides the expected modularity, but determining where the definition of the autoassemble bean is declared is still somewhat ambiguous. For example, as a developer, seeServiceConfigHow to know exactly@Autowired AccountRepositoryWhere are beans defined? It’s not explicit in the code, which might be good. Remember, spring tools provides eclipse with tools to render graphics that show how all the objects are connected, which may be what you need. Your Java ide makes it easier to find all the declarations and usesAccountRepositoryType and display it quickly@BeanMethod and the return type.

If this ambiguity is unacceptable, and you want to get it directly from within the IDE@ConfigurationClass to navigate to another@ConfigurationClass, consider the autoassemble configuration class itself. The following example shows how to do this:

@Configuration
public class ServiceConfig {

    @Autowired
    private RepositoryConfig repositoryConfig;

    @Bean
    public TransferService transferService() {
        // navigate 'through' the config class to the @Bean method!
        return new TransferServiceImpl(repositoryConfig.accountRepository());
    }
}

In the previous case,AccountRepositoryComplete display definition. But,ServiceConfigNow tightly coupled toRepositoryConfig。 This is the trade-off. By using interface based or abstract class based@ConfigurationClass can alleviate this tight coupling to some extent. Consider the following example:

@Configuration
public class ServiceConfig {

    @Autowired
    private RepositoryConfig repositoryConfig;

    @Bean
    public TransferService transferService() {
        return new TransferServiceImpl(repositoryConfig.accountRepository());
    }
}

@Configuration
public interface RepositoryConfig {

    @Bean
    AccountRepository accountRepository();
}

@Configuration
public class DefaultRepositoryConfig implements RepositoryConfig {

    @Bean
    public AccountRepository accountRepository() {
        return new JdbcAccountRepository(...);
    }
}

@Configuration
@Import({ServiceConfig.class, DefaultRepositoryConfig.class})  // import the concrete config!
public class SystemTestConfig {

    @Bean
    public DataSource dataSource() {
        // return DataSource
    }

}

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
    TransferService transferService = ctx.getBean(TransferService.class);
    transferService.transfer(100.00, "A123", "C456");
}

Now?ServiceConfigAnd specificDefaultRepositoryConfigLoosely coupled, and the built-in ide tools are still very useful: you can easily access themRepositoryConfigThe level of implementation. In this way, navigation@ConfigurationClasses and their dependencies are no different from the usual process of navigating interface based code.

If you want to smoothly start the order in which these beans are created, consider declaring them as@Lazy(for first access rather than creation at startup) or@DependsOnOther beans (make sure that the other specified beans are created before the current bean is created and are not affected by the latter’s direct dependencies).

Conditionally include@ConfigurationClass or@Beanmethod

Conditional enable or disable complete, depending on some system state@ConfigurationClass or even single@BeanMethod, usually very useful. Note: can be enabled / disabled@ConfigurationClass or@ConfigurationClass@Beanmethod. A common example is to use@ProfileAnnotations to activate beans, only when in springEnvironmentdesignatedprofileWhen activated (view bean definition profiles details).

@ProfileAnnotations are called annotations by using a very flexible annotation called@ConditionalRealized.@ConditionalNOTE indicates that the@BeanSpecific information should be consulted beforeorg.springframework.context.annotation.Conditionrealization.

ConditionThe implementation interface provides amatches(…)Method, which returns true or false. For example, the following listing showsConditionYes@ProfileReal implementation:

@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    // Read the @Profile annotation attributes
    MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
    if (attrs != null) {
        for (Object value : attrs.get("value")) {
            if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
                return true;
            }
        }
        return false;
    }
    return true;
}

see@ConditionalThe documentation is more detailed.

Combining Java and XML configuration

Spring’s@ConfigurationClass cannot100%To replace spring XML. Some tools, such as spring XML namespaces, are still ideal ways to configure containers. When it is convenient or necessary to use XML, you can choose: use“ClassPathXmlApplicationContextInstantiate the container as XML centric or by using theAnnotationConfigApplicationContextAnd Java configuration center.@ImportResourceAnnotations can be imported into XML as needed.

XML centric@ConfigurationUse of class

Boot the spring container from XML and include it in a special way@ConfigurationClass might be better. For example, in a large existing code base that uses spring XML, create as needed@ConfigurationAnd it’s easier to include existing classes in XML files. Later in this section, we’ll show you how to use it in this “XML centric” context@ConfigurationClass.

  • statement@ConfigurationIt is similar to the common spring < bean / > element

    remember@ConfigurationClass is ultimately a bean definition in the container. In this series of examples, we create@ConfigurationName the classAppConfigAnd include it in system test- config.xml Similar to the < bean / > definition in. because<context:annotation-config/>Opened, container inAppConfigMedium recognition@ConfigurationAnnotate and handle the @ bean method declaration.

    The following example shows the normal configuration in Java:

    @Configuration
    public class AppConfig {
    
        @Autowired
        private DataSource dataSource;
    
        @Bean
        public AccountRepository accountRepository() {
            return new JdbcAccountRepository(dataSource);
        }
    
        @Bean
        public TransferService transferService() {
            return new TransferService(accountRepository());
        }
    }

    The following example showssystem-test-config.xmlPart of the document:

    <beans>
        <!-- enable processing of annotations such as @Autowired and @Configuration -->
        <context:annotation-config/>
        <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
    
        <bean class="com.acme.AppConfig"/>
    
        <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
    </beans>

    The following example shows the possiblejdbc.propertiesDocument:

    jdbc.url=jdbc:hsqldb:hsql://localhost/xdb
    jdbc.username=sa
    jdbc.password=
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml");
        TransferService transferService = ctx.getBean(TransferService.class);
        // ...
    }

    staysystem-test-config.xmlIn the file, AppConfig < bean / > does not declare an ID element. While this is acceptable, it is unnecessary because no other beans refer to it, and it is unlikely to get it explicitly from the container by name. Again,DataSourceBeans can only be assembled automatically by type, so explicit beans are not strictly requiredid

  • use<context:component-scan/>choice@Configurationclass

    because@ConfigurationMeta annotations are@Component, by@ConfigurationAnnotated classes are candidates for automatic scanning of components. Using the same scenario as described in the previous example, we can redefine itsystem-test-config.xmlTo use component scanning. Note that in this scenario, we do not need to display the declaration of<context:annotation-config/>Because<context:component-scan/>Activate the same function.

    The following example shows the modifiedsystem-test-config.xmlDocument:

    <beans>
        <!-- picks up and registers AppConfig as a bean definition -->
        <context:component-scan base-package="com.acme"/>
        <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
    
        <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
    </beans>

@ConfigurationClass centered XML and@ImportResourceCombined use of

In application,@ConfigurationClasses are the main mechanism for configuring containers, but you may still need to use at least some XML. In this scenario, you can use the@ImportResourceAnd define the XML you need. This implements a “Java centric” approach to configuring containers and keeping XML to a minimum. The following example shows how to use it@ImportResourceAnnotations to implement Java centric configuration and use XML when needed:

@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource() {
        return new DriverManagerDataSource(url, username, password);
    }
}

properties-config.xml

<beans>
    <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>

jdbc.properties

public static void main(String[] args) {
    ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
    TransferService transferService = ctx.getBean(TransferService.class);
    // ...
}

Code example:com.liyong.ioccontainer.starter.BaseJavaConfigAndXmlIocContainer

author

Personally engaged in the financial industry, I have worked in Chongqing’s first-class technical team, such as yijifu, Sijian technology, a car Hailing platform, etc. at present, I am in charge of the construction of unified payment system in a bank. I have a strong interest in the financial industry. At the same time, it also practices big data, data storage, automatic integration and deployment, distributed microservices, responsive programming, artificial intelligence and other fields. At the same time, it is also keen to share technology and create official account and blog site.

Blog address: http://youngitman.tech

CSDN: https://blog.csdn.net/liyong1…

The official account of WeChat:

Spring 5 Chinese parsing core - IOC container based on Java container configuration

Technical exchange group:

Spring 5 Chinese parsing core - IOC container based on Java container configuration