Detailed Spring 3.0 Dependency injection implementation based on Annotation (RPM)

Source: Internet
Author: User

Identify a class as a Bean using @Repository, @Service, @Controller, and @Component

Spring has introduced several annotations to simplify the development of spring since version 2.0. @Repository annotations belong to the first batch introduced, which identifies the class of the data Access layer (DAO layer) as a Spring Bean. Just label the note on the DAO class. Also, in order for Spring to be able to scan classes in the Classpath and identify @Repository annotations, you need to enable the Bean's automatic scanning function in the XML configuration file, which can be achieved by <context:component-scan/>. As shown below:

The DAO class is first declared as a Bean package Bookstore.dao using @Repository  ;  @Repository public  class Userdaoimpl implements userdao{...}  Second, start Spring's automatic scanning function in the XML configuration file <beans ... >     <context:component-scan base-package= "Bookstore.dao"/> ... ... </beans>

In this way, we no longer need to explicitly use <bean/> for bean configuration in XML. Spring automatically scans all class files under the specified Base-package package and its sub-packages when the container is initialized, and all classes labeled @Repository will be registered as Spring beans.

Why @Repository can only be labeled on the DAO class? This is because the annotation does not only recognize the class as a Bean, but it also encapsulates the data access exception that is thrown in the annotated class as a Spring data access exception type. Spring itself provides a rich and data-access exception structure that is independent of the specific data-access technology used to encapsulate exceptions thrown by different persistence-layer frameworks, making exceptions independent of the underlying framework.

Spring 2.5 Adds an additional three annotations with similar features on @Repository basis: @Component, @Service, @Constroller, respectively, for different levels of software systems:

    • @Component is a generalization concept that simply represents a component (Bean) that can function at any level.
    • @Service usually work in the business layer, but currently the function is the same as @Component.
    • @Constroller usually works on the control layer, but currently the function is the same as @Component.

By using @Repository, @Component, @Service, and @Constroller annotations on the class, Spring automatically creates the corresponding Beandefinition object and registers it in ApplicationContext. These classes become Spring-managed components. These three annotations, in addition to classes that work at different levels of software, are used in exactly the same way as @Repository.

In addition, in addition to the above four annotations, the user can create a custom annotation, and then annotate the annotation @Component, then the custom annotation has the same functionality as the @Component. However, this feature is not commonly used.

When a bean is automatically detected, its bean name is generated based on the Beannamegenerator policy of that scanner. By default, name is used as the name of the Bean for @Component, @Repository, @Service, and @Controller that contain the Name property. If this annotation does not contain a name value or any other component found by the custom filter, the default Bean name will be the unqualified class name at the beginning of the lowercase. If you do not want to use the default bean naming policy, you can provide a custom naming policy. First implement the Beannamegenerator interface, confirming that a default parameterless construction method is included. Then provide a fully qualified class name when configuring the scanner, as follows:

<beans ...>  <context:component-scan     base-package= "a.b" name-generator= "A.simplenamegenerator"/ >  </beans>

Like the spring bean configured through XML, the bean identified by the above annotations has a default scope of "singleton", in order to match these four annotations, the scope of the bean can be specified while labeling the bean, and Spring 2.5 introduces a @Scope annotation 。 You only need to provide the scope name when using the annotation, as follows:

@Scope ("prototype")  @Repository public  class Demo {...}

If you want to provide a custom scope resolution policy without using an annotation-based approach, simply implement the Scopemetadataresolver interface, confirming that a default constructor with no parameters is included. Then provide the fully qualified class name when configuring the scanner:

<context:component-scan base-package= "a.b" scope-resolver= "Footmark. Simplescoperesolver "/>

Back to top of page

Specifying lifecycle callback methods using @PostConstruct and @PreDestroy

Spring beans are managed by the Spring IoC container, initialized and destroyed by the container (the prototype type is not managed by the container after the container is initialized), and typically we do not need to focus on the container's initialization and destruction of the bean, as the spring A Bean created through a constructor or factory method is already initialized and immediately available. However, in some cases, we may need to do some additional initialization or destruction operations manually, which is usually for some resource acquisition and release operations. Spring 1.x provides two ways for a user to specify a method for performing a lifecycle callback.

The first approach is to implement the two interfaces provided by Spring: Initializingbean and Disposablebean. If you want to perform some custom actions after the bean initialization is complete, you can have the bean implement the Initializingbean interface, which contains a afterpropertiesset () method that will be called automatically after the container has set properties for the bean. If the bean implements the Disposablebean interface, the container will call the Destroy () method of the interface before destroying the bean. The disadvantage of this approach is that the Bean class implements the interface provided by spring, increasing the coupling between the code and the spring framework, and is therefore not recommended.

The second approach is to use <bean> 's Init-method and Destroy-method properties in the XML file to specify the callback method after initialization and before destruction, and the code does not need to implement any interfaces. The values of these two properties are the initialization and destruction methods in the corresponding Bean class, the method name is arbitrary, but the method cannot have parameters. Examples are as follows:

<bean id= "UserService"  class= "Bookstore.service.UserService"  init-method= "init" destroy-method= " Destroy "> ...     </bean>

Spring 2.5 provides support for JSR-250, based on the retention of the above two methods. The JSR-250 specification defines two annotations for specifying the declaration period method: @PostConstruct and @PreDestroy. These two annotations are very simple to use, simply by labeling them on the callback method that was executed after initialization or destroying the callback method that was executed earlier. Because annotations are used, it is necessary to configure the appropriate Bean post processor, i.e. add the following line to the XML:

<context:annotation-config/>

Comparing the above three methods of specifying the life cycle callback method, the first one is not recommended, not only its usage is not as flexible as the latter two ways, but also implicitly increases the coupling between the code and the framework. In the following two ways, developers can choose one of them according to their habits, but it is best not to mix them, so as not to make maintenance more difficult.

Back to top of page

Use @Required for Bean dependency checking

The role of dependency checking is to determine whether the appropriate Setter method for a given Bean is invoked at the time of instantiation. Instead of judging if the field already exists. When Spring makes a dependency check, it only determines whether the property uses Setter injection. If a property is not injected with a Setter, even though the constructor has injected a value for the property, Spring still thinks it does not inject, throwing an exception. In addition, Spring does not have to be injected through the Setter, and there is no requirement for the injected value, even if the injected <null/>,spring is considered to have performed a dependency injection.

The <bean> tag provides the Dependency-check property for dependency checking. The value of this property includes the following:

    • None-dependency checking is not performed by default. You can use the Default-dependency-check property on the <beans> tab to change the default value.
    • Simple-Checks the original base type and collection type.
    • Objects--Checks for complex types (except for types other than simple check types).
    • All-check all types.

Older versions are set in the configuration file using Dependency-check, with the disadvantage of coarse granularity. Use the @Required annotations provided by Spring2.0 to provide finer-grained control. @Required annotations can only be labeled on the Setter method. Because the nature of dependency injection is to check that the Setter method is called, instead of actually checking to see if the property is assigned a value and what value is assigned. If the annotation is marked in a non-setxxxx () type method, it is ignored.

In order for Spring to handle this annotation, the corresponding Bean post processor needs to be activated. To activate the Post processor, simply add the following line to the XML.

<context:annotation-config/>

When a Setter method that is labeled @Required is not called, Spring throws an exception when parsing, reminding the developer to set the corresponding property.

Back to top of page

Use @Resource, @Autowired, and @Qualifier to specify automatic assembly policies for beans

Automatic assembly means that Spring, when assembling a bean, injects a bean of the reference type that a bean needs according to the specified automatic assembly rules. The <bean> element provides a Autowire property that specifies the automatic assembly type, which has the following options:

    • No-explicitly specifies that automatic assembly is not used.
    • ByName-If there is a bean with the same name as the current property, the bean is used for injection. If the name matches but the type does not match, an exception is thrown. If there is no matching type, nothing is done.
    • Bytype--If there is a bean (the same type or subtype) that is consistent with the current property type, the bean is used for injection. Bytype is able to identify the factory method, which is able to identify the return type of the Factory-method. Throws an exception if there are more than one type-consistent Bean. If there is no matching type, nothing is done.
    • constructor--similar to Bytype, except that it is for constructor injection. Throws an exception if there is currently no Bean that matches the parameter type of the constructor. When using this type of assembly mode, the constructors with the most parameters are preferred.
    • AutoDetect-The automatic assembly of Bytype or constructor according to the Bean's introspection mechanism. If the Bean provides a default constructor, Bytype is used, otherwise automatic assembly is done with constructor.

When using automatic assembly of the Bytype or constructor type, automatic assembly also supports arrays of reference types or uses generic collections, so Spring checks all types of beans in the container to make a collection or array to perform the injection. For a MAP type that uses generics, if the key is of type String, Spring also automatically executes the assembly, with all types matching the bean as the value and the bean's name as the key.

We can add the Default-autowire property to <beans> and set the default auto-encapsulation policy. The default value is "no". If you specify a property or a Constructor-arg label while using automatic assembly, the value that is explicitly specified overrides the auto-assembled value. The current auto-encapsulation does not support simple types such as primitive types, String, Class, and their array types.

When matching by type (possibly Bytype, constructor, AutoDetect), there may be multiple beans in the same type, and if the injected property is an array, a collection, or a Map, this may not be a problem, but if it is simply a reference type, an exception is thrown. There are several ways to resolve this:

    • Cancels the automatic assembly feature of the Bean, using explicit injection. We may not want a bean to be used as a candidate for the automatic encapsulation of other beans, and we can add autowire-candidate= "false" to the <bean>. (The Autowire-candidate attribute and the Autowire property are independent of each other and are irrelevant.) A Bean can set Autowire-candidate to False while using the Autowire attribute. In addition, we can set the Default-autowire-candidates property of <beans>, where you can specify a matching pattern that can be used to automatically assemble candidate beans, such as Default-autowire-candidates= "*serv,*dao", which means that all beans whose names end in Serv or DAO are listed as candidates, others are ignored, equivalent to other beans specified as autowire-candidate= " False ", you can explicitly specify autowire-candidate=" true "for <bean> at this time. The settings specified on <bean> override the settings specified on <beans>.
    • If you have the preferred bean in more than one type of bean, you can set the <bean> 's primary property to "true" so that the bean will be used for assembly when it is automatically assembled. You cannot set Autowire-candidate to false at this time.
    • If you are using more than Java version 5, you can use annotations for finer-grained control.
Perform automated assembly using @Autowired and @Qualifier annotations

Assembly using @Autowired annotations can only be matched by type. @Autowired annotations can be used in Setter methods, constructors, fields, and even common methods, provided that the method must have at least one parameter. @Autowired can be used for arrays and collection types that use generics. Spring then injects all the type-compliant beans in the container. When a @Autowired callout acts on a map type, if the map's key is of type String, Spring adds the bean that has the type of value corresponding to map in the container, using the bean's ID or name as the The key of the MAP.

When a @Autowired callout acts on a normal method, it has a side effect, which is called when the container initializes the Bean instance. Of course, the premise is that automatic assembly is performed, and the method will not be executed for situations where assembly conditions are not met.

An exception is thrown when the @Autowired is marked and the auto-injection is not satisfied. We can add a Required=false attribute to the @Autowired annotation to change this behavior. In addition, each class can have only one constructor @Autowired. The required () property is true. Otherwise, there will be a problem. If more than one constructor is labeled with the @Autowired, Spring will use the greedy algorithm to match the constructor (the constructor is the longest).

@Autowired Another function is to label it in the Beanfactory type, ApplicationContext type, Resourceloader type, applicationeventpublisher type, Messagesource type, Spring automatically injects instances of these implementation classes without the need for additional action.

When there are multiple beans in a container with the same type as the one that needs to be injected, the injection cannot be executed, and we can add a candidate value to the @Autowired by adding a @Qualifier callout after the @Autowired, providing a String of value as the candidate be The name of an. Examples are as follows:

@Autowired (Required=false)  @Qualifier ("PPP") Public  void Setperson (person p) {}

@Qualifier can even be used as a parameter for a method (in cases where the method has only one argument, we can place the @Qualifer label above the method declaration, but it is recommended to precede the parameter), for example:

@Autowired (required=false) public  void SayHello (@Qualifier ("PPP") person p,string name) {}

We can specify the qualifier name of a Bean in the configuration file as follows:

<bean id= "Person" class= "Footmark.spring.Person" >     <qualifier value= "PPP"/>  </bean>

If the bean's qualifier name is not explicitly specified, then the default name is the bean's name. In general, qualifier should have business implications, such as "domain", "persistent" and so on, rather than "person" mode.

We can also label the @Qualifier on the collection type, so all beans with the same Qualifier name and the specified value will be injected.

Finally, the property values for each custom annotation need to be specified in the configuration file. We can use the <meta> tag instead of the <qualifier/> tag, and if the <meta> tags and <qualifier/> tags appear at the same time, use <qualifier> Label. If there is no <qualifier> tag, the <qualifier> label is encapsulated with the key-value pairs provided by <meta>. Examples are as follows:

<bean class= "Footmark. HelloWorld ">  <qualifier type=" Moviequalifier ">  <attribute key=" format "value=" VHS "/>  <attribute key= "Genre" value= "comedy"/>  </qualifier>  </bean>  <bean class= " Footmark. HelloWorld ">  <meta key=" format "value=" DVD "/>  <meta key=" Genre "value=" Action "/>  </ Bean>

The post-processing registration for the @Autowired annotation is similar to the previous one, just add the following line to the configuration file:

<context:annotation-config/>

If @Autowired inject system types such as Beanfactory, ApplicationContext, Resourceloader, and so on, then @Qualifier is not required, even if @Qualifier annotations are provided, they will be ignored For automatic assembly of custom types, automatic assembly matching fails if @Qualifier annotations are used and there are no beans matching the name.

Using @Resource and @Qualifier annotations in JSR-250

If you want to perform automatic assembly by name, you should use the @Resource annotations provided by JSR-250 instead of using a combination of @Autowired and @Qualifier.

Automatic encapsulation is performed @Resource using ByName. @Resource annotations can be used for Setter methods with one parameter, for fields, and for common methods with one parameter. @Resource annotations have a Name property that specifies the name of the Bean that corresponds to the configuration file. If you do not specify a Name property, the default value is the name of the field or property. The @Resource and @Qualifier mates are still true, but the @Qualifier is almost equivalent to the Name property for @Resource.

If the @Resource does not specify a Name property, then the use of the ByName match fails, and the Bytype continues with the match, and throws an exception if it fails again. If you do not explicitly specify the Name property for a @Resource annotation, label it in the Beanfactory type, ApplicationContext type, Resourceloader type, Applicationeventpublisher type, Messagesource type, Spring automatically injects instances of these implementation classes without the need for additional action. The Name property does not need to be specified (or specified as ""), otherwise the injection fails, and if @Qualifier is used, the annotation is ignored. For injection of user-defined types, the @Qualifier and name are equivalent and are not ignored.

<bean> 's primary and Autowire-candidate properties are still valid for @Resource, @Autowired.

Back to top of page

Using @Configuration and @Bean to make a Bean declaration

While Spring has provided more than 10 annotations since the release of version 2.0, the annotations provided are intended to simplify the configuration of the XML in some cases, rather than replacing the XML configuration. This can be seen from the initialization class of the Spring IoC container: The most common implementation class for the ApplicationContext interface is Classpathxmlapplicationcontext and Filesystemxmlapplicationcontext, as well as Portlet-oriented xmlportletapplicationcontext and web-oriented xmlwebapplicationcontext, are all oriented to of XML. Spring 3.0 adds two additional implementation classes: Annotationconfigapplicationcontext and Annotationconfigwebapplicationcontext. As you can see from the name, they are an IoC container initialization class that is born for annotations and relies directly on annotations as the source of container configuration information. Since Annotationconfigwebapplicationcontext is a web version of Annotationconfigapplicationcontext, its usage is almost no different than the latter, so this article will Annotationconfigapplicationcontext as an example to explain.

Annotationconfigapplicationcontext is paired with @Configuration and @Bean annotations, and since then the XML configuration is no longer the only way to configure the Spring IoC container. There is a competitive relationship between the two, but in most cases it is a collaborative relationship, and the combination makes the Spring IoC container configuration simpler and more powerful.

Previously, we wrote the configuration information in XML, and now using annotations, the vector of configuration information was transferred from the XML file to the Java class. We usually end the class name for the class that holds the configuration information with "Config", such as Appdaoconfig.java, Appserviceconfig.java, and so on. We need to add @Configuration annotations on the class that specifies the configuration information to make it clear that the class is the source of information for the Bean configuration. And Spring has the following requirements for the class that labels the Configuration:

    • The configuration class cannot be final;
    • The configuration class cannot be localized, that is, the configuration class cannot be defined inside a method of another class;
    • The configuration class must have an argument-free constructor.

Annotationconfigapplicationcontext identifies the return value of the method that is @Bean in the configuration class as a Spring Bean and registers it in the container, managed by the IoC container. The function of the @Bean is equivalent to the <bean/> tag in the XML configuration. Examples are as follows:

@Configuration public  class bookstoredaoconfig{     @Bean public     Userdao Userdao () {return new Userdaoimpl ();     @Bean public     Bookdao Bookdao () {return new Bookdaoimpl ();}  }

When Spring resolves to the above file, it will recognize all the methods of the callout @Bean, execute it, and register the return value of the method (here, Userdaoimpl and Bookdaoimpl objects) in the IoC container. By default, the Bean's name is the method name. Therefore, the XML configuration equivalent to the above configuration is as follows:

<bean id= "Userdao" class= "Bookstore.dao.UserDaoImpl"/>  <bean id= "Bookdao" class= " Bookstore.dao.BookDaoImpl "/>

@Bean has the following four properties:

    • Name--Specifies the name of one or more beans. This is equivalent to the Name property of <bean> in the XML configuration.
    • Initmethod--When the container initializes the Bean, it invokes the method specified by the property. This is equivalent to the Init-method property of <bean> in the XML configuration.
    • Destroymethod-this property is similar to the Initmethod function, and the method specified by the property is called before the container destroys the Bean. This is equivalent to the Destroy-method property of <bean> in the XML configuration.
    • Autowire--Specifies the automatic assembly policy for Bean properties, which is a value of three static properties of the Autowire type. Autowire.by_name,autowire.by_type,autowire.no. Compared to the value of the Autowire attribute in the XML configuration, there is less constructor here, because constructor is meaningless here.

@Bean does not directly provide properties for the specified scope, it can be implemented by @Scope, and the usage of @Scope is listed above.

The following describes the container initialization based on annotations. Annotationconfigapplicationcontext provides three constructors for initializing a container.

    • Annotationconfigapplicationcontext (): The constructor initializes an empty container that contains no Bean information and needs to register the configuration class later by calling its register () method and calling Refresh () method to refresh the container.
    • Annotationconfigapplicationcontext (Class<?> ... annotatedclasses): This is the most commonly used constructor, by passing the configuration class involved to the constructor, To implement the beans in the corresponding configuration class to be automatically registered in the container.
    • Annotationconfigapplicationcontext (String ... basepackages): This constructor automatically scans all classes under the given package and its child packages, and automatically recognizes all Spring beans and registers them in the container. It not only recognizes the configuration class of the callout @Configuration and resolves it correctly, but also recognizes classes that use @Repository, @Service, @Controller, @Component annotations.

In addition to using the third type of constructor above to let the container automatically scan the Bean's configuration information, Annotationconfigapplicationcontext also provides a scan () method, which is similar to the above, which is mainly used to dynamically increase after container initialization Bean into the container. After the method is called, it is often necessary to manually call refresh () to flush the container immediately for the change to take effect immediately.

It is important to note that Annotationconfigapplicationcontext, when parsing a configuration class, registers itself as a Bean for the configuration class itself, because it is @Component labeled @Configuration the annotation itself is defined. So it can be said that a @Configuration is also a @Component. In most cases, developers do not use the bean, and ideally, the bean should be transparent to the developer. The definition of @Configuration is as follows:

@Target ({elementtype.type})  @Retention (retentionpolicy.runtime)  @Documented  @Component public  @ Interface Configuration {  String value () default "";  }

In a general project, for structural clarity, it is common to define multiple XML configuration files based on the software's module or structure, and then define a portal configuration file that uses <import/> to organize other configuration files. Finally, simply pass the file to the Classpathxmlapplicationcontext constructor. For annotation-based configurations, Spring also provides similar functionality by defining a Portal configuration class and using @Import annotations to introduce additional configuration classes on that class, and finally simply passing the portal class to Annotationconfigapplicationcontext. Specific examples are as follows:

@Configuration  @Import ({bookstoreserviceconfig.class,bookstoredaoconfig.class}) public  class Bookstoreconfig{...}

Back to top of page

Mixing the Bean configuration with XML and annotations

The purpose of designing @Configuration and @Bean is not to completely replace XML, but to have a more viable alternative to XML. Since spring has since been released, the spring development team has been simplifying the XML configuration, making the XML configuration very mature, plus a series of namespaces supported by Spring 2.0, making the XML configuration a simple, powerful way to define beans 。 Furthermore, some of the advanced features of the XML configuration are currently not directly supported by the relevant annotations. Therefore, in most current projects, you either use a purely XML configuration for the bean configuration, or make the configuration of the bean with annotations as the primary and XML as a supplement.

The coexistence of the two causes is mainly attributed to three reasons: first, most of the projects that are currently being developed with spring are based on XML configuration, and spring, while introducing annotations, must ensure that annotations can coexist with XML, which is the premise; Since annotations are introduced late, the functionality is not as powerful as XML for many years, so for complex configurations, annotations are difficult to independently, and XML mates are still needed for some time to solve the problem. In addition, spring's Bean configuration is decoupled from the Spring core module, so changing the configuration mode is transparent to the spring framework itself. Spring can easily add support for annotations by using the Bean Post processor (beanpostprocessor). This is a very easy thing to achieve in technology.

To use a hybrid configuration, you first need to determine which configuration is the primary. The different answers to this question will directly affect the way the implementation is implemented. However, there is no need to worry about this, because whether it is based on XML, or annotation-based, configuration is simple and easy to understand. There is no wrong decision, because it is just a different way of behaving. Let's first assume that the XML configuration is the primary scenario.

For large projects that already exist, it may be that the Bean is initially configured in XML, followed by a gradual addition of annotation support, when we simply define the class @Configuration labeled as a normal <bean> in the XML configuration file, while registering the The Bean post processor is ready. Examples are as follows:

Suppose the following @Configuration class exists: Package bookstore.config;  Import bookstore.dao.*;  @Configuration public  class myconfig{  @Bean public     Userdao Userdao () {         return new Userdaoimpl ();     At  this point, just make the following declaration in XML: <beans ... > ...    <context:annotation-config/>     <bean class= "Demo.config.MyConfig"/>  </beans>

Since the Bean post processor for annotations is enabled, when ApplicationContext resolves to the Myconfig class, it is discovered that the class has annotated @Configuration annotations, and then handles the method of labeling @Bean in that class. Registers the return value of these methods as the total Bean of the container.

For the above approach, if there are multiple classes labeled @Configuration, you need to list them in the XML file individually. Another way is to use the previously mentioned automatic scanning feature, which is configured as follows:

<context:component-scan base-package= "Bookstore.config"/>

In this way, Spring scans the classes in all Demo.config packages and their sub-packages, identifying all classes marked with @Component, @Controller, @Service, @Repository annotations, as @Configuration The annotations themselves are also annotated with @Component, and Spring will be able to identify @Configuration annotation classes and parse them correctly.

For annotation-centric configuration, simply use @ImportResource annotations to introduce the existing XML, as follows:

@Configuration  @ImportResource ("Classpath:/bookstore/config/spring-beans.xml") Public  class myconfig{...}  The container initialization process is consistent with a purely configuration-centric approach: annotationconfigapplicationcontext CTX =               new Annotationconfigapplicationcontext ( Myconfig.class); ......

Detailed Spring 3.0 Dependency injection implementation based on Annotation (RPM)

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.