20191230 Spring official documents (Core 1.12)

1.12. Java-based configuration container

1.12.1. The basic concept: @Bean and @Configuration

@BeanExamples of the method for indicating annotation, to configure and initialize the new object to be managed by the Spring IoC container. For those familiar with Spring's <beans/>man of the XML configuration, the role of @ Bean and comments The same elements. You can Spring for any @Component use @Bean annotated. However, they are most commonly associated with @Configuration use with bean.

@Configuration expressed annotate the class whose main purpose is defined as Bean source. Further, @ Configuration class allows to define dependencies between @Bean Bean by another method call in the same class.

Complete @Configuration and "Lite" @Bean mode?

If not used @Configuration annotated @Bean method declared in the class, they are referred to as processing the "thin" mode. In a @Component Bean or even a common method declared in class is considered to be "thin", the main purpose of which contains different classes, and methods @Bean there is an additional bonus. For example, the service management component can be disclosed to the container by an additional view @Bean method applied on each component class. In this case, @ Bean factory method is a common method of mechanism.

@Configuration different with a complete, streamlined @Bean method can not declare dependencies between Bean. Instead, they operate on its internal state comprising components, and may also operate in accordance with parameters which may be stated. Therefore, such a method should not be called @Bean @Bean other methods. Indeed, each of these methods is merely a method for specific plant bean references, without any special runtime semantics. Positive impact here is, having to apply at runtime CGLIB subclass, so there is no restriction in the class design (that is, contains the class may be final, and so on).

, @ Bean method will be declared in the case of common @Configuration class in order to ensure that you always use the "full" mode, so cross-reference method will be redirected to the life cycle management of the container. This can be prevented by regular Java method calls invoke the same @Bean unexpectedly, thus helping to reduce subtle errors in "Lite" mode untraceable runtime.

1.12.2. Examples of use of the Spring container AnnotationConfigApplicationContext

AnnotationConfigApplicationContextAchieved not only acceptable @Configurationtype as input may receive a general @Componentclass and using the JSR-330metadata annotation category.

When providing @Configuration class as input, @ Configuration class itself will be registered as Bean definition, and the class is declared in all @Bean method will also be registered as Bean definition.

When provided @Component and JSR-330 type, which are registered as bean definitions, and it is assumed that metadata DI these classes when necessary, for example, @Autowiredor @Inject.

// 基本用法
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);

// 手动注册配置类
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();

// 以编程方式启用扫描功能
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme");
ctx.refresh();

By AnnotationConfigWebApplicationContext support Web applications

<web-app>
    <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
        instead of the default XmlWebApplicationContext -->
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>
            org.springframework.web.context.support.AnnotationConfigWebApplicationContext
        </param-value>
    </context-param>

    <!-- Configuration locations must consist of one or more comma- or space-delimited
        fully-qualified @Configuration classes. Fully-qualified packages may also be
        specified for component-scanning -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.acme.AppConfig</param-value>
    </context-param>

    <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Declare a Spring MVC DispatcherServlet as usual -->
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
            instead of the default XmlWebApplicationContext -->
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>
                org.springframework.web.context.support.AnnotationConfigWebApplicationContext
            </param-value>
        </init-param>
        <!-- Again, config locations must consist of one or more comma- or space-delimited
            and fully-qualified @Configuration classes -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>com.acme.web.MvcConfig</param-value>
        </init-param>
    </servlet>

    <!-- map all requests for /app/* to the dispatcher servlet -->
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>

1.12.3. Use @Bean comments

You can be @Configurationannotated classes or @Componentuse annotation class @Beannotes.

Declaring a Bean

By default, the same name as the bean method names.

Can @Beanreturn type declaration of your way to use the interface (or base class).

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

Non-inert according to a single embodiment thereof bean instantiation declaration order, so you may see different types of matching results, depending on when the other component according to the type attempted match undeclared (e.g. @Autowired TransferServiceImpl, only in the example only after resolving of transferService bean).

If you reference the type consistently through the service interface declaration, the @Bean return type can be safely added to the design decisions. However, achieve multiple interfaces or components to achieve its potential component type references, the most specific statement might return type (at least with reference to the specific type of the required injection point your bean like) more secure.

Bean dependence

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

Analytical constructor dependency injection mechanism based on almost the same

Receiving lifecycle callbacks

Any class support with the definition of notation @Bean conventional lifecycle callbacks, and you can use the JSR-250 @PostConstructand @PreDestroycomments.

Spring also fully supports regular lifecycle callbacks. If the bean implements InitializingBean, DisposableBeanor Lifecycle, the container will call their respective methods.

Also fully supports the standard *Awareset of interfaces (e.g. BeanFactoryAware, BeanNameAware, MessageSourceAware, ApplicationContextAwareetc.).

@Bean annotation support specify any initialization and destruction callback methods, like the Spring XML init-methodand destroy-methodbean element attributes, as shown in 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, using the Java configuration having a common definition closeor shutdownbean method is automatically registered by a callback destruction. If you have a public close or shutdown method, and do not want to call it when the container is closed, you can add @Bean(destroyMethod="")to the bean definition to disable the default ( inferred) mode.

By default, you might want to do this to get through JNDI resources, because their life cycle is managed in an external application. In particular, make sure to always operate DataSource, because on the Java EE application server is problematic.

The following example shows how to prevent the destruction of DataSource automatic callback:

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

In addition, for @Bean method, commonly used programming JNDI lookup method is to use Spring JndiTemplateor JndiLocatorDelegatehelper, or directly using JNDI InitialContext, but do not use JndiObjectFactoryBeanvariant (which will force you to return type is declared as FactoryBeantype, rather than the actual target type this makes it difficult to cross-reference calls) in other @Bean methods intended to refer to resources provided herein.

For example BeanOne foregoing comments, called directly during the construction init()methods are equally effective, as shown in the following example:

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

When you work directly with Java, you can perform any operations on objects without having to always rely on the container life cycle.

Bean scope specified

The default range is singleton, but you can use @Scopeannotations to cover it, as in the following example:

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

Spring provides a convenient way by the scope scope proxy process dependent. The easiest way to create such a proxy configuration is the use of XML <aop:scoped-proxy/>elements. Use @Scopeannotations in Java bean configuration can proxyModeprovide the same support properties. The default value is agentless ( ScopedProxyMode.NO), but you can specify ScopedProxyMode.TARGET_CLASSor ScopedProxyMode.INTERFACES.

If a reference from an XML document scopes proxy example transplanted into our Java @Bean, then it is similar to the following:

// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
public UserPreferences userPreferences() {
    return new UserPreferences();
}

@Bean
public Service userService() {
    UserService service = new SimpleUserService();
    // a reference to the proxied userPreferences bean
    service.setUserPreferences(userPreferences());
    return service;
}

Custom Bean name

By default, configured to use the class @Beanname as the name of the method result of the bean. However, you can use the nameattribute overrides this function, as shown in the following example:

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

Bean alias

It is sometimes desirable to provide multiple names for a single Bean, Bean called aliases. For this purpose @Beana comment nameaccepts a String array property. The following example shows how to set a plurality of aliases bean:

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

Bean Description

In some cases, provide a more detailed text description would be helpful about the bean. When exposing bean (possibly through JMX) to be monitored, it is particularly useful.

To add a description to @Beanbe used @Descriptionannotations, as shown in the following example:

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

1.12.4. Use @Configuration comments

@ConfigurationIt is a class-level annotation indicating that the object is defined by the source Bean. @Configuration bean class method declarations by public @Bean comment. The method calls for @Bean @Configuration class may also be used to define dependencies between Bean.

Inject dependencies between bean

When the bean interdependence, represents a dependency relationship is like to make a call to another bean method relies as simple, as in the following example:

@Configuration
public class AppConfig {

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

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

Only when the declaration method @Bean @Configuration class, this declaration bean inter dependency method works. You can not use the dependencies between ordinary @Component class declaration bean.

Find Method Injection

As mentioned earlier, look for the injection method is an advanced feature, you should rarely use. In the single embodiment has scoped bean dependent prototype scope bean, this is useful. Java for this type of arrangement provides a natural way to achieve this pattern. The following example shows how to use the 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();
}

By using Java configuration, you can create a cover abstract createCommand()method of CommandManagersubclass, which will find a new (prototype) command object in some way. 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();
        }
    }
}

For more information about Java-based configuration of how to work within the

Consider the following example, this example shows a method annotated with @Bean 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();
    }
}

Since a new instance of clientDao () method creates ClientDaoImpl and return it, it is often desirable to have two instances (each service a). It is definitely a problem: In Spring, instantiated bean has a singleton scope by default. This is a magical place: all classes at startup @Configuration use CGLIB subclass. In the sub-category, sub-method before calling the method and create a new instance of the parent, first check whether there are any cache (scope) of the bean container.

According to the scope of the bean, the behavior may be different. We are here talking about a single case.

Starting Spring 3.2, CGLIB no longer need to add to your class path, because CGLIB the class has been repackaged org.springframework.cglibunder and directly included in the spring-coreJAR.

Because CGLIB dynamically add functionality at startup, so there are some limitations. In particular, the class can not be disposed finalof. However, since version 4.3, allowing the use of any configuration based on constructors, including the use of single or @Autowired declared non-default constructor for the default injection.

If you want to avoid any restrictions imposed CGLIB, please consider @Bean declare your method on non-@Configuration class (for example, declared on the common @Component class). Then @Bean method does not cross between the intercept method calls, so you have to rely exclusively on where the constructor or method level of dependency injection.

1.12.5. The composition of Java-based configuration

Spring Java-based configuration function lets you write annotations, which can reduce the complexity of configuration.

Use @Import comments

As used in the Spring XML file <import/>elements to help the same modular configuration, @Importannotation allows @Bean definitions, as another example of the configuration loaded from the class shown:

@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();
    }
}

Starting Spring Framework 4.2, @ Import also supports the reference to the conventional component class, similar to AnnotationConfigApplicationContext.registerthe method. If you want to explicitly define all components as an entry point by using some type configuration, so as to avoid scanning assembly, this feature is particularly useful.

Injection dependence on imported defined @Bean

@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 is another way to achieve the same result. Remember, remember, @Configurationthe class ultimately just another bean container: this means that they can use @Autowiredto @Valueinject the same functions other bean.

In this manner, the dependency injection is the simplest one. During the context initialization process @Configuration early class, and in this way forced to inject dependencies may cause unexpected early initialization. As illustrated, the injection parameters based possible.

In addition, please pay special attention BeanPostProcessorand BeanFactoryPostProcessor@Bean defined. It should normally be those declared static @Beanmethod, without triggering instance of the class which contains configuration. Otherwise, @ Autowired and @Value not like the configuration work because it is too early to be created as a bean instance.

@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");
}

From the Spring Framework 4.3 supports only start @Configuration class constructor injection. Also note that if the target bean only defines a constructor without specifying @Autowired.

@Configuration class or conditionally @Bean method comprising

Based on some arbitrary system state, conditionally enable or disable complete even a single @Bean @Configuration class method is often useful. A common example is used only enabled when a specific profile in Spring Environment in @Profilecomments activate Bean.

@Profile comment is called by the use of a more flexible @Conditionalannotation actual implementation.

ConditionImplementation of the interface provides a matches(..)method returns true or false.

Combination of Java and XML configuration

Spring's support @Configuration class is not intended to completely replace 100% Spring XML. Some tools (for example Spring XML namespaces) remains the ideal way to container configuration. In easy to use XML or necessary under the circumstances, you can select: Use ClassPathXmlApplicationContextthe "XML-centric" approach to instantiate the container, or AnnotationConfigApplicationContextby way of "Java-centric" instantiation container. @ImportResourceAnnotations can import XML as needed.

XML-centric use of @Configuration class

The @Configurationclass declaration is pure Spring <bean/>elements

<beans>
    <context:annotation-config/>
    <bean class="com.acme.AppConfig"/>
</beans>

Use <context:component-scan />pickup @Configurationclass

In this case, we do not need to explicitly declare <context:annotation-config/>, because <context:component-scan/>the same functionality is enabled.

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

To @Configuration class-centric XML and @ImportResource

@ImportResource("classpath:/com/acme/properties-config.xml")

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

By @PropertySourceintroducing a properties file

Guess you like

Origin www.cnblogs.com/huangwenjie/p/12121368.html