Spring Java-based container configuration

Source: Internet
Author: User

Spring Java-based container configuration

Over the years, a large number of XML configurations and complex dependency management in Spring have been criticized. To implement XML-free development experience, Spring adds new Configuration annotations to support the Java Config development mode. The most important annotations are @ Configuration and @ Bean.

Basic concepts: @ Bean and @ Configuration

In Spring's new Java-configuration support, the core part is the @ Configuration annotation class and the @ Bean annotation class.

@ Bean annotation is used to indicate a method instantiation, configuration, and initialization of a new object managed by the Spring container. Familiar with Spring For XML configuration users, @ Bean annotation and The element works the same. You can use the @ Bean annotation method in any Spring @ Component. However, they are usually used together with the @ Configuration annotation beans.

Annotation of A Class Using @ Configuration means that its main purpose is to serve as the source of bean definition. In addition, the @ Configuration class allows dependencies between beans (inter-bean). You only need to simply call other @ bean methods in the class.
Example:

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

The above AppConfig class is equivalent to the following Spring XML:


      
   
  
Full @ Configuration VS 'lite '@ Beans Mode

When the @ Bean method is declared in a class that is not annotated by @ Conguration, this is called processing in the 'shortest 'mode. For example, in a @ Component object, even the bean Methods declared in a common class are all processed in 'shortest.
Unlike the complete @ Configuration, it is difficult to declare dependencies between beans by using the simplified @ Bean method. Generally, when operating in the simplified mode, you should not call another @ Bean method in one @ Bean method.

One recommended method is to use the @ Bean method only in the @ Configuration class. This ensures that the 'complete' mode is always used to avoid the @ Bean method being accidentally called multiple times, reduce the subtle bugs that are difficult to track in a streamlined mode.

Use AnnotationConfigApplicationContext to instantiate a Spring container

AnnotationConfigApplicationContext is added in Spring 3.0. The ApplicationContext implementation of this function can receive the @ Configuration class as the input, can also receive the common @ Component class, and the class that uses the JSR-330 Metadata Annotation.

When the @ Configuration class is used as the input, the @ Configuration class itself is registered as a bean definition, and all the declared @ Bean methods in the class are also registered as bean definitions.

When the @ Component and JSR-330 classes are used as inputs, they are registered as bean definitions and use DI metadata as needed, such as @ Autowired or @ Inject.

Constructor instantiation

Similar to instantiating a ClassPathXmlApplicationContext, you can use the Spring XML file as the input. when instantiating an AnnotationConfigApplicationContext, you can use the @ Configuration class as the input. This allows the Spring container to be completely configured with zero XML:

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

As mentioned above, AnnotationConfigApplicationContext is not limited to only using the @ Configuration class. Any @ Component or JSR-330 annotation class can be used as an input to the AnnotationConfigApplicationContext constructor. For 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();}

Assume that MyServiceImpl, Dependency1, and Dependency2 use Spring dependency injection annotations, such as @ Autowired.

*register(Class …?)Instantiation

You can use a constructor without parameters to instantiate AnnotationConfigApplicationContext, and then useregister()Method to configure the container. This method is useful when constructing an AnnotationConfigApplicationContext programmatically.

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();}
Enable scan(String…?)Component Scanning

To enable component scanning, you only need to annotate your @ Configuration class as follows:

@Configuration@ComponentScan(basePackages = com.acme)public class AppConfig  {    ...}

Note:Experienced Spring users will be familiar with Springcontext:Equivalent XML declaration of a namespace:


      
   
  

In the preceding examplecom.acmeTo find any classes annotated by @ Component, and these classes will be registered as Spring bean definitions in the container. AnnotationConfigApplicationContext exposedscan(String…?)Method to achieve the same container scanning function:

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

Note:Remember that the @ Configuration class is annotated by @ Component, so they are also candidates for Component scanning! In the above example, assume that AppConfig is defined incom.acmeIn the package (or any lower-level package ),scan()During this period, it will also be scanned whenrefresh()All its @ Bean methods will be processed and registered as bean definitions in the container.

Use AnnotationConfigWebApplicationContext to Support web Applications

AnnotationConfigWebApplicationContext is the WebApplicationContext variant of AnnotationConfigApplicationContext. It is used when configuring Spring ContextLoaderListener servlet listener and Spring MVC DispatcherServlet. The following web. xml snippet configures a typical Spring MVC web application. Note the usage of contextClass context-param and init-param:


      
       
           
    
     
ContextClass
            
    
     
Org. springframework. web. context. support. AnnotationConfigWebApplicationContext
        
       
       
           
    
     
ContextConfigLocation
            
    
     
Com. acme. AppConfig
        
       
       
           
    
     
Org. springframework. web. context. ContextLoaderListener
        
       
       
           
    
     
Dispatcher
            
    
     
Org. springframework. web. servlet. DispatcherServlet
            
            
                
     
      
ContextClass
                 
     
      
Org. springframework. web. context. support. AnnotationConfigWebApplicationContext
             
            
            
                
     
      
ContextConfigLocation
                 
     
      
Com. acme. web. MvcConfig
             
        
       
       
           
    
     
Dispatcher
            
    
     
/App /*
        
   
  
@ Bean annotation usage

@ Bean is a method-level annotation, XML Element equivalence. This annotation provides some Provided elements, such as init-method, destroy-method, autowiring, andname.
You can use the @ Bean annotation in a @ Configuration annotation or @ Component annotation class.

Declare a bean

To declare a bean, simply use @ Bean to annotate a method. You can use this method to register a bean defined in ApplicationContext. The type is specified by the return value of the method. By default, bean names and method names are the same. The following is a simple @ Bean method declaration example:

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

The above configuration is equivalent to the following Spring XML:


      
   
  

Both Declarations create a bean named transferService in ApplicationContext, which is bound to an object instance of the TransferServiceImpl type:transferService -> com.acme.TransferServiceImpl.

Bean dependency

A @ Bean annotation method can have any number of parameters to describe the dependencies required to build the bean. For example, if our TransferService requires an AccountRepository, we can provide this dependency using a method parameter:

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

This processing mechanism is very important for Constructor-based dependency injection. For more information, see relevant chapters.

Receive lifecycle callback

Each class defined using the @ Bean annotation supports regular lifecycle callbacks and can use the @ PostConstruct and @ PreDestroy annotations from the JSR-250. For more information, see the JSR-250 annotations, general Spring lifecycle Callbacks are also supported. If a bean implements InitializingBean, DisposableBean, or Lifecycle, their corresponding methods will be called by the container.

Standard*AwareAll interfaces are supported, such as BeanFactoryAware, BeanNameAware, MessageSourceAware, and ApplicationContextAware. @ Bean annotation supports specifying any number of initialization and destruction callback methods, similar to Spring XMLbeanElementinit-methodAnddestroy-methodAttribute:

public class Foo {    public void init() {        // initialization logic    }}public class Bar {    public void cleanup() {        // destruction logic    }}@Configurationpublic class AppConfig {    @Bean(initMethod = init)    public Foo foo() {        return new Foo();    }    @Bean(destroyMethod = cleanup)    public Bar bar() {        return new Bar();    }}

Note:By default, beans defined using Java config have a publiccloseOrshutdownMethod is automatically registered as a destroy callback. If you have a publiccloseOrshutdownMethod, and do not want to call it when the container is closed, you simply need@Bean(destroyMethod=)Add to bean definition to disable the default inference (inferred) mode. For a resource obtained through JNDI, because its lifecycle is managed by the server rather than the application, you may want to do so by default, especially for resources such as DataSource:

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

Of course, in the above Foo example, it is called directly in the constructorinit()The method is also valid:

@Configurationpublic class AppConfig {    @Bean    public Foo foo() {        Foo foo = new Foo();        foo.init();        return foo;    }    // ...}

Note:When using Java directly, you can do anything you want to do with your object, instead of always relying on the lifecycle of the container.

Specify bean Scope

1. Use the @ Scope Annotation

You can specify a specific scope for the Bean defined by @ bean annotation. You can use any standard scope defined in Bean Scopes scope. The default Scope is singleton, but you can use @ Scope to overwrite it:

@Configurationpublic class MyConfiguration {    @Bean    @Scope(prototype)    public Encryptor encryptor() {        // ...    }}

2. @ Scope and scoped-proxy

Spring provides a convenient way to handle the dependencies of the scope through scoped proxies. The simplest way is to create such a proxy, Which is configuredElement. In Java, the @ Scope annotation and proxyMode attribute can achieve the same functions. NO proxy (ScopedProxyMode. NO) by default, but you can specify ScopedProxyMode. TARGET_CLASS or ScopedProxyMode. INTERFACES.
If you want to transition from the scoped proxy example in the XML reference document to @ Bean using Java, it may look as follows:

// an HTTP Session-scoped bean exposed as a proxy@Bean@Scope(value = session, proxyMode = ScopedProxyMode.TARGET_CLASS)public UserPreferences userPreferences() {    return new UserPreferences();}@Beanpublic Service userService() {    UserService service = new SimpleUserService();    // a reference to the proxied userPreferences bean    service.setUserPreferences(userPreferences());    return service;}

3. Custom bean name

By default, the configuration class uses the @ Bean method name as the name of the result bean. This function can benameOverwrite attributes.

@Configurationpublic class AppConfig {    @Bean(name = myFoo)    public Foo foo() {        return new Foo();    }}

4. Bean alias

Sometimes it is necessary to create multiple names for a single bean. The name attribute of @ Bean annotation can receive a String array for this purpose.

@Configurationpublic class AppConfig {    @Bean(name = { dataSource, subsystemA-dataSource, subsystemB-dataSource })    public DataSource dataSource() {        // instantiate, configure and return DataSource bean...    }}

5. Bean description

It is helpful to provide a detailed text description for a bean, especially when beans are exposed (possibly through JMX) for monitoring purposes.

You can use the @ Description annotation to add a Description for a @ Bean:

@Configurationpublic class AppConfig {    @Bean    @Description(Provides a basic example of a bean)    public Foo foo() {        return new Foo();    }}
@ Configuration annotation usage

@ Configuration annotation is a Class-level annotation, which means that the object is the source of a bean definition. The @ Configuration class declares beans through the public @ Bean annotation method. The @ Bean method on the @ Configuration class can be called to define dependencies between beans.

Bean dependency Injection

When @ Beans depends on other Beans, you only need to call another bean in one bean method to express this dependency:

@Configurationpublic class AppConfig {    @Bean    public Foo foo() {        return new Foo(bar());    }    @Bean    public Bar bar() {        return new Bar();    }}

In the preceding example, foo bean obtains a reference pointing to bar through constructor injection.

Note:The method for declaring dependencies between beans is only valid for @ bean methods in the @ Configuration class. You cannot use the common @ Component class to declare references between beans.

Lookup method Injection

As mentioned above, lookup method injection is an advanced feature and should be used less. This method is useful when a bean in the singleton scope depends on a bean in the prototype scope. Java configuration provides a natural way to implement this type of configuration.

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

With Java configuration support, you can create a CommandManager subclass. Here, the abstract createCommand () method is used to find a new (prototype) command object to overwrite:

@Bean@Scope(prototype)public AsyncCommand asyncCommand() {    AsyncCommand command = new AsyncCommand();    // inject dependencies here as required    return command;}@Beanpublic CommandManager commandManager() {    // return new anonymous implementation of CommandManager with command() overridden    // to return a new prototype Command object    return new CommandManager() {        protected Command createCommand() {            return asyncCommand();        }    }}
How Java-based configuration content works

The following example shows that a @ Bean annotation method is called twice:

@Configurationpublic 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()And thenclientService2(). Because this method creates a new ClientDaoImpl instance and returns it, you can expect two instances (each service has one instance ). This is definitely a problem: in Spring, the instantiated beans have a scope of singleton by default. This is where magic is generated: All @ Configuration classes are subclass by CGLIB during startup (proxy ). In the subclass, The subclass method first checks whether the container caches the corresponding beans (scoped). If no cache is available, the method of the parent class is called to create a new instance. Note that after Spring3.2, you do not need to add CGLIB dependencies because CGLIB is repackaged into org. springframework and directly included in spring-core JAR.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.