In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces how to implement Spring3 dependency injection based on Annotation. The content is very detailed. Interested friends can use it for reference. I hope it will be helpful to you.
Summary: the dependent configuration of Spring is loosely coupled with the kernel of the Spring framework. However, until Spring 3.0, using XML for dependency configuration was almost the only option. The advent of Spring 3.0 has changed that by providing a series of annotations for dependency injection, which makes Spring IoC a viable alternative to XML files.
Use @ Repository, @ Service, @ Controller, and @ Component to identify the class as Bean
Since version 2.0 of Spring, some annotations have been introduced to simplify the development of Spring. The @ Repository annotation is among the first to be introduced, which is used to identify the class of the data access layer (DAO layer) as Spring Bean. You only need to mark the annotation on the DAO class. At the same time, in order for Spring to scan classes in the classpath and recognize @ Repository annotations, you need to enable automatic scanning of Bean in the XML configuration file, which can be achieved. As follows:
/ / first declare the DAO class as Bean using @ Repository
Package bookstore.dao; @ Repository
Public class UserDaoImpl implements UserDao {. }
/ / secondly, start the automatic scanning function of Spring in the XML configuration file
……
……
Beans >
In this way, we no longer need to explicitly use the configuration of Bean in XML. Spring will automatically scan all class files under the package specified by base-package and its subpackages when the container is initialized, and all classes marked with @ Repository will be registered as Spring Bean.
Why can @ Repository only be annotated on the DAO class? This is because the purpose of this annotation is not only to identify the class as Bean, but also to encapsulate the data access exception thrown in the annotated class as the data access exception type of Spring. Spring itself provides a rich data access exception structure that is independent of the specific data access technology, which is used to encapsulate the exceptions thrown by different persistence layer frameworks, making the exceptions independent of the underlying framework.
Spring 2.5 adds three additional annotations with similar functionality to @ Repository: @ Component, @ Service, and @ Constroller, which are used at different levels of the software system:
♦ @ Component is a generalized concept that simply represents a component (Bean) and can be applied at any level.
♦ @ Service usually works at the business layer, but currently this function is the same as @ Component.
♦ @ Constroller usually works at the control layer, but currently this 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 with ApplicationContext. These classes become Spring managed components. These three annotations are used in exactly the same way as @ Repository, except for classes at different software levels.
In addition, in addition to the four comments above, you can create a custom annotation and then mark @ Component on it, so that the custom annotation has the same functionality as the @ Component. However, this function is not commonly used.
When a Bean is automatically detected, its bean name is generated according to the scanner's BeanNameGenerator policy. By default, for @ Component, @ Repository, @ Service, and @ Controller that contain the name attribute, the value of name is taken as the name of Bean. If this annotation does not contain name values or other components discovered by the custom filter, the default Bean name will be an unqualified class name that begins with lowercase. If you do not want to use the default bean naming strategy, you can provide a custom naming strategy. First implement the BeanNameGenerator interface and confirm that a default parameterless constructor is included. Then provide a fully qualified class name when configuring the scanner, as follows:
As with Spring Bean configured through XML, the default scope of Bean identified by the above annotations is "singleton". To match these four annotations, you can specify the scope of Bean while tagging Bean. Spring 2.5 introduces the @ Scope annotation. When using this annotation, you only need to provide the name of the scope, as shown below:
@ Scope ("prototype") @ Repository public class Demo {… }
If you want to provide a custom scope resolution strategy instead of using an annotation-based method, just implement the ScopeMetadataResolver interface and make sure it contains a default constructor with no parameters. Then provide the fully qualified class name when configuring the scanner:
Package= "a.b" scope-resolver= "footmark.SimpleScopeResolver" / >
Specify lifecycle callback methods using @ PostConstruct and @ PreDestroy
Spring Bean is managed by the Spring IoC container and initialized and terminated by the container (after the prototype type is initialized by the container, it is not managed by the container). Usually, we do not need to pay attention to the initialization and destruction of the Bean by the container. The Bean created by the Spring through the constructor or factory method is initialized and available immediately. However, in some cases, we may need to do some additional initialization or destruction operations manually, usually for some resource acquisition and release operations. Spring 1.x provides two ways for users to specify ways to perform lifecycle callbacks.
The first way 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 Bean implement the InitializingBean interface, which contains an afterPropertiesSet () method that the container will automatically call after setting the property 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 having the Bean class implement the interface provided by Spring increases the coupling between the code and the Spring framework, so it is not recommended.
The second way is to use the init-method and destroy-method attributes in the XML file to specify callback methods after initialization and before destruction, and the code does not need to implement any interfaces. The values of these two properties are 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 >
Spring 2.5 provides support for JSR-250 while retaining the above two approaches. The JSR-250 specification defines two annotations for specifying declaration cycle methods: @ PostConstruct and @ PreDestroy. These two annotations are very easy to use, as long as you mark them on the callback method executed after initialization or on the callback method executed before destruction, respectively. Because annotations are used, you need to configure the corresponding Bean post-processor, that is, add the following line to the XML:
Comparing the above three ways of specifying lifecycle callback methods, the first one is not recommended, not only is it not as flexible as the latter two methods, but also virtually increases the coupling between the code and the framework. Developers can choose one of the latter two methods according to their usage habits, but it is best not to mix them so as not to increase the difficulty of maintenance.
Use @ Required to check the dependency of Bean
The purpose of dependency checking is to determine whether the corresponding Setter methods for a given Bean are all called when instantiated. Instead of determining whether the field already has a value. When Spring does dependency checking, it only determines whether the property uses Setter injection. If a property does not use Setter injection, even if a value has been injected into the property through the constructor, Spring still assumes that it does not perform the injection and throws an exception. In addition, Spring does not have any requirements for the value of the injection, regardless of whether the injection is performed through Setter, and even if it is injected, Spring believes that dependency injection is performed.
The tag provides the dependency-check attribute for dependency checking. The values of this attribute include the following:
♦ none-dependency checking is not performed by default. You can use the default-dependency-check attribute on the tag to change the default value.
♦ simple-checks for primitive primitive types and collection types.
♦ objects-checks for complex types (types other than those checked by simple).
♦ all-check for all types.
The old version used dependency-check to set it in the configuration file, but the disadvantage was that it was coarse-grained. Using the @ Required annotation provided by Spring2.0 provides finer-grained control. The @ Required annotation can only be annotated on top of the Setter method. Because the essence of dependency injection is to check whether the Setter method has been called, not to actually check whether the property is assigned and what value is assigned. Methods that are not of type setXxxx () are ignored if the annotation is annotated.
In order for Spring to process the annotation, you need to activate the corresponding Bean post-processor. To activate the post-processor, simply add the following line to XML.
When a Setter method marked @ Required is not called, Spring throws an exception during parsing to remind the developer to set the corresponding property.
Use @ Resource, @ Autowired, and @ Qualifier to specify the automatic assembly strategy for Bean
Auto-assembly means that when Spring assembles Bean, it injects the Bean of the reference type required by a certain Bean according to the specified automatic assembly rules. Element provides an autowire attribute that specifies the autoassembly type, which has the following options:
♦ no-explicitly specifies that autoassembly is not used.
♦ byName-if there is a Bean that matches the name of the current attribute, this 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 matches the current attribute type, this Bean is used for injection. ByType is able to recognize factory methods, that is, the return type of factory-method. If there is more than one Bean of the same type, an exception is thrown. If there is no matching type, nothing is done.
♦ constructor-similar to byType, except that it is for constructor injection. If there is currently no Bean that matches the parameter type of the constructor, an exception is thrown. When using this assembly mode, priority is given to matching the constructor with the most parameters.
♦ autodetect-decides whether to use byType or constructor for automatic assembly according to Bean's introspection mechanism. If Bean provides a default constructor, use byType; otherwise use constructor for automatic assembly.
When using autoassembly of byType or constructor types, autoassembly also supports arrays of reference types or collections that use generics, so that Spring checks all type-matching Bean in the container, forms a collection or array, and then performs injection. For Map types that use generics, if the key is a String type, Spring also automatically performs the assembly, taking the Bean that matches all types as the value and the name of Bean as the key.
We can add the default-autowire attribute to set the default auto-encapsulation policy. The default is "no". If you specify a property or constructor-arg tag while using autoassembly, the value explicitly specified overrides the autoassembly value. Current automatic 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 Bean of the same type, which may be fine if the injected property is an array, collection, or Map, but if it is a simple reference type, an exception will be thrown. The solutions are as follows:
♦ removes the auto-assembly feature of the Bean and uses explicit injection. We may not want a Bean to be used as a candidate for other Bean to perform automatic encapsulation, but we can add autowire-candidate= "false" to it. (the autowire-candidate property and the autowire property are independent and independent of each other. A Bean can set autowire-candidate to false while using the autowire feature.) In addition, we can set the default-autowire-candidates property, in which we can specify a matching pattern that can be used to automatically assemble candidate Bean, such as default-autowire-candidates= "* serv,*dao", which means that all Bean whose names end in serv or dao are listed as candidates, while others are ignored, which means that all other Bean are specified as autowire-candidate= "false". In this case, you can explicitly specify autowire-candidate= "true". The settings specified on the override the settings specified on the.
♦ if you have a preferred Bean among multiple Bean of the same type, you can set the primary property to "true" so that the Bean is preferred for automatic assembly. Autowire-candidate cannot be set to false at this time.
If ♦ is using Java 5 or later, you can use annotations for finer-grained control.
Perform automatic assembly using @ Autowired and @ Qualifier annotations
Assembling with the @ Autowired annotation can only be matched by type. The @ Autowired annotation can be used for Setter methods, constructors, fields, or even generic methods, as long as the method has at least one parameter. @ Autowired can be used for arrays and collection types that use generics. Spring then injects Bean that matches all types in the container. When the @ Autowired annotation acts on the Map type, if the key of Map is String, Spring will add the Bean of all types in the container corresponding to the value of Map, and use the id or name of Bean as the key of Map.
A side effect when the @ Autowired annotation acts on a normal method is that the method 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 implemented if the assembly conditions are not met.
When @ Autowired is marked and automatic injection is not satisfied, an exception will be thrown. We can change this behavior by adding a required=false attribute to the @ Autowired annotation. In addition, the @ Autowired.required () attribute of only one constructor in each class is true. Otherwise, something will go wrong. If multiple constructors are annotated at the same time with @ Autowired, Spring will match the constructor with a greedy algorithm (the constructor is the longest).
Another purpose of @ Autowired is that if you mark it on BeanFactory type, ApplicationContext type, ResourceLoader type, ApplicationEventPublisher type, MessageSource type, then Spring will automatically inject instances of these implementation classes without additional operation.
When there are multiple Bean types in the container that are the same as those that need to be injected, the injection will not be performed. We can add a candidate value to @ Autowired by adding a @ Qualifier tag after @ Autowired, providing a value of type String as the name of the candidate Bean. Examples are as follows:
@ Autowired (required=false) @ Qualifier ("ppp") public void setPerson (person p) {}
@ Qualifier can even act on the parameters of a method (in the case of a method with only one parameter, we can place the @ Qualifer tag above the method declaration, but it is recommended to put it before the parameter), as an example:
@ Autowired (required=false) public void sayHello (@ Qualifier ("ppp") Person pcent string name) {}
We can specify the qualifier name of a Bean in the configuration file as follows:
Bean >
If the qualifier name of Bean is not explicitly specified, the default name is Bean. In general, qualifier should have a business meaning, such as "domain", "persistent", etc., rather than in a similar "person" way.
We can also mark @ Qualifier on the collection type, so that all Bean with the same qualifier name as the specified value will be injected.
Finally, the property value of each custom annotation needs to be specified in the configuration file. We can use it.
Tags are used instead of tags, and if the tag and the tag appear at the same time, then the tag is preferred. If there is no label, the tag is encapsulated with the key-value pair provided. Examples are as follows: qualifier > bean > bean >
The post-processing registration for @ Autowired annotation is similar to the previous one. You only need to add the following line to the configuration file:
If @ Autowired is injected with BeanFactory, ApplicationContext, ResourceLoader and other system types, @ Qualifier is not required, and even if the @ Qualifier annotation is provided, it will be ignored. For custom type auto-assembly, if the @ Qualifier annotation is used and there is no Bean with a matching name, the auto-assembly matching fails.
Use @ Resource and @ Qualifier annotations in JSR-250
If you want to automate according to name, you should use the @ Resource annotation provided by JSR-250 instead of a combination of @ Autowired and @ Qualifier.
@ Resource performs automatic encapsulation using byName. The @ Resource annotation can be applied to Setter methods, fields with one parameter, and common methods with one parameter. The @ Resource annotation has a name attribute that specifies the corresponding name of Bean in the configuration file. If the name property is not specified, the default value is the name of the field or property. The combination of @ Resource and @ Qualifier is still valid, but @ Qualifier is almost equivalent to the name attribute for @ Resource.
If @ Resource does not specify the name attribute, if it fails to match with byName, it will fall back and use byType to continue matching, and if it fails again, an exception will be thrown. Without explicitly specifying the name attribute for the @ Resource annotation, if you mark it on the BeanFactory type, ApplicationContext type, ResourceLoader type, ApplicationEventPublisher type, and MessageSource type, then Spring will automatically inject instances of these implementation classes without additional operation. The name attribute does not need to be specified (or specified as "") at this point, otherwise the injection fails; if @ Qualifier is used, the annotation will be ignored. For user-defined type injection, @ Qualifier is equivalent to name and is not ignored.
The primary and autowire-candidate properties of are still valid for @ Resource and @ Autowired.
Declare Bean using @ Configuration and @ Bean
Although Spring has provided more than a dozen annotations since the release of version 2.0, the annotations provided are only intended to simplify the configuration of XML in some cases, not to replace the XML configuration. This can be seen from the initialization classes of the Spring IoC container: the most common implementation classes of the ApplicationContext interface are ClassPathXmlApplicationContext and FileSystemXmlApplicationContext, as well as Portlet-oriented XmlPortletApplicationContext and web-oriented XmlWebApplicationContext, both of which are XML-oriented. Two other implementation classes have been added to Spring 3.0: AnnotationConfigApplicationContext and AnnotationConfigWebApplicationContext. As you can see from the name, they are created for annotations and rely directly on the IoC container initialization classes from which annotations are the source of container configuration information. Because AnnotationConfigWebApplicationContext is the web version of AnnotationConfigApplicationContext, its usage is almost no different from the latter, so this article will take AnnotationConfigApplicationContext as an example.
AnnotationConfigApplicationContext is paired with @ Configuration and @ Bean annotations. Since then, XML configuration is no longer the only way to configure Spring IoC containers. There is a competitive relationship between the two in a certain range, but they still cooperate with each other in most cases, and the combination of the two makes the configuration of the Spring IoC container simpler and more powerful.
Previously, we centrally wrote the configuration information in XML, but now using annotations, the carrier of configuration information is transferred from the XML file to the Java class. We usually end the class name of the class used to store configuration information with "Config", such as AppDaoConfig.java, AppServiceConfig.java, and so on. We need to annotate the class used to specify configuration information with @ Configuration to make it clear that the class is the source of information for the Bean configuration. And Spring has the following requirements for classes that label Configuration:
♦ configuration class cannot be final
The ♦ configuration class cannot be localized, that is, it cannot be defined inside the methods of other classes
The ♦ configuration class must have a no-parameter constructor.
AnnotationConfigApplicationContext identifies the return value of the method marked @ Bean in the configuration class as Spring Bean, registers it in the container, and is managed by the IoC container. The function of @ Bean is equivalent to the label 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 parses to the above file, it recognizes all methods labeled @ Bean, executes them, and registers the return value of the method (in this case, the UserDaoImpl and BookDaoImpl objects) with the IoC container. By default, the name of Bean is the method name. Therefore, the XML configuration equivalent to the above configuration is as follows:
@ Bean has the following four properties:
♦ name-specifies the name of one or more Bean. This is equivalent to the name attribute in the XML configuration.
♦ initMethod-after initializing the Bean, the container calls the method specified by this property. This is equivalent to the init-method attribute in the XML configuration.
♦ destroyMethod-this property is similar to the initMethod function in that the method specified by this property is called before the container destroys the Bean. This is equivalent to the destroy-method attribute in the XML configuration.
♦ autowire-specifies the auto-assembly strategy for the Bean attribute, which is the three static attributes of type Autowire. Autowire.BY_NAME,Autowire.BY_TYPE,Autowire.NO . Compared with the value of the autowire attribute in the XML configuration, there is less constructor here because constructor no longer makes sense here.
@ Bean does not directly provide the properties of the specified scope, which can be achieved through @ Scope, and the use of @ Scope is listed above.
The following is about annotation-based container initialization. AnnotationConfigApplicationContext provides three constructors to initialize the container.
♦ AnnotationConfigApplicationContext (): this constructor initializes an empty container that does not contain any Bean information and needs to register the configuration class later by calling its register () method and refreshing the container by calling the refresh () method.
♦ AnnotationConfigApplicationContext (Class... AnnotatedClasses): this is the most commonly used constructor that automatically registers the Bean in the corresponding configuration class with the container by passing the configuration class involved to it.
♦ AnnotationConfigApplicationContext (String... BasePackages): this constructor automatically scans all classes under the given package and its subpackages, and automatically identifies all Spring Bean and registers them with the container. It not only recognizes the configuration classes marked @ Configuration and parses them correctly, but also recognizes classes marked with @ Repository, @ Service, @ Controller, and @ Component.
In addition to using the third type of constructor above to allow the container to automatically scan the configuration information of Bean, AnnotationConfigApplicationContext also provides a scan () method, which is similar to the function above, which is mainly used to dynamically add Bean to the container after initialization. After calling this method, you usually need to manually call refresh () to refresh the container immediately so that the changes take effect immediately.
It is important to note that when AnnotationConfigApplicationContext parses the configuration class, it registers the configuration class itself as a Bean, because the @ Configuration annotation is annotated by @ Component when it is defined. So you can say that an @ Configuration is also an @ Component. In most cases, the Bean is not available to developers, and ideally, the Bean should be transparent to developers. 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 the sake of clarity, multiple XML configuration files are usually defined according to the module or structure of the software, and then an entry configuration file is defined, which is used to organize other configuration files. Finally, you just need to pass the file to the constructor of ClassPathXmlApplicationContext. For annotation-based configurations, Spring provides similar functionality by defining a portal configuration class, introducing other configuration classes using the @ Import annotation on this class, and finally passing the portal class to AnnotationConfigApplicationContext. Specific examples are as follows:
@ Configuration @ Import ({BookStoreServiceConfig.class,BookStoreDaoConfig.class}) public class BookStoreConfig {… }
Mixed use of XML and annotations for Bean configuration
@ Configuration and @ Bean were not designed to completely replace XML, but to provide a viable alternative to XML. Since the release of Spring, the Spring development team has continued to simplify XML configuration, which makes XML configuration very mature. In addition, a series of namespace support has emerged since Spring 2.0, which makes XML configuration a simple and powerful way to define Bean. Moreover, some advanced features of XML configuration are currently not directly supported by relevant annotations. Therefore, in most current projects, either pure XML configuration is used for Bean configuration, or annotations-based configuration and XML-assisted configuration are used for Bean configuration.
The coexistence of the two can be attributed to three reasons: first, the vast majority of projects developed with Spring are almost based on XML configuration. While introducing annotations, Spring must ensure that annotations can coexist harmoniously with XML, which is the premise. Second, due to the late introduction of annotations, the function is not as powerful as XML, which has been developed for many years. Therefore, it is difficult for annotations to be independent of complex configurations, and the cooperation of XML is still needed to solve the problem for a period of time. In addition, the configuration mode of Spring's Bean is decoupled from the core module of Spring, so changing the configuration mode is transparent to the framework of Spring itself. Spring can easily add support for annotations by using the Bean post-processor (BeanPostProcessor). This is very easy to do in terms of technical implementation.
To use a mixed configuration, you first need to determine which configuration is the main one. Different answers to this question will have a direct impact on the way it is implemented. However, there is no need to worry about this, because whether it is based on XML or annotations, the configuration is simple and easy to understand. There is no wrong decision here, because it is just a different way of expression. Let's first assume that the configuration is based on XML.
For existing large-scale projects, Bean may initially be configured with XML, and then annotations will be gradually added. In this case, we only need to define the classes annotated by @ Configuration in the XML configuration file as normal, and register the Bean post-processor that handles annotations. 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, you only need to make the following declaration in XML:
…… Beans >
Because the Bean post-processor for annotations is enabled, when ApplicationContext parses to the MyConfig class, you will find that the class is marked with @ Configuration annotations, and then the methods labeled @ Bean in this class will be processed, and the return values of these methods will be registered as the total Bean of the container.
For the above methods, if there are multiple classes labeled @ Configuration, you need to list them one by one in the XML file. Another way is to use the automatic scanning feature mentioned earlier, which is configured as follows:
In this way, Spring will scan all classes in the demo.config package and its subpackages to identify all classes marked with @ Component, @ Controller, @ Service, and @ Repository annotations. Because the @ Configuration annotation itself is annotated with @ Component, Spring will be able to identify the @ Configuration annotated classes and parse them correctly.
For annotation-centric configuration, simply use the @ ImportResource annotation to introduce the existing XML, as shown below:
@ Configuration @ ImportResource ("classpath:/bookstore/config/spring-beans.xml") public class MyConfig { }
/ / the initialization process of the container is consistent with a purely configuration-centric approach:
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext (MyConfig.class);
Concluding remarks
Starting with version 2. 0, each update of Spring provides more new annotations for developers to use. This satisfies the appetite of annotation enthusiasts. But as mentioned earlier, Spring provides more annotations not to one day replace XML configuration, but to give developers another choice. The two ways of declaring Bean have their own characteristics. XML is more flexible and relatively mature, which is familiar to most Spring developers; annotations are very simple to use, but they are still in the stage of development. It is difficult for us to say which of the two configuration methods is better or worse, but if we can flexibly match the two ways, we will be able to further improve the efficiency of development.
On how to implement Spring3 Annotation-based dependency injection to share here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.