Spring5: @Autowired Annotations, @Resource annotations, and @service annotations

Source: Internet
Author: User

What are annotations

The traditional spring approach is to use an. xml file to inject beans or to configure AOP and things, and there are two drawbacks to doing so:

1. If all the content is configured in the. xml file, the. xml file will be very large, and if the. xml file is separated by demand, then the. xml file will be much larger. In summary, this will result in the readability and maintainability of the configuration file becoming very low

2. Switching between. java files and. xml files in development is a hassle, and this incoherent thinking can reduce the efficiency of development.

To address these two issues, spring introduces annotations, which, by means of "@XXX", allow annotations to be tightly combined with Java beans, greatly reducing the volume of the configuration file and increasing the readability and cohesion of Java beans.

This article, which is about the three most important spring annotations, namely @autowired, @Resource and @service, hopes to be able to articulate the usage of these three annotations in a limited space.

Do not use annotations

Look at a spring example that does not use annotations, which, on the basis of this example, is changed to the annotated version, so that you can see the difference between using and not using annotations, first defining a tiger:

public class tiger{    private String tigername = "tigerking";        Public String toString ()    {        return "Tigername:" + Tigername;    }}

Define a monkey again:

public class monkey{    private String monkeyname = "monkeyking";        Public String toString ()    {        return "Monkeyname:" + Monkeyname;    }}

Define a Zoo:

public class zoo{    private Tiger Tiger;    Private Monkey Monkey;        public void Settiger (Tiger Tiger)    {        This.tiger = Tiger;    }        public void Setmonkey (Monkey Monkey)    {        this.monkey = Monkey;    }        Public Tiger Gettiger ()    {        return tiger;    }        Public Monkey Getmonkey ()    {        return Monkey;    }        Public String toString ()    {        return tiger + "\ n" + Monkey;    }}

The spring configuration file reads:

<?xml version= "1.0" encoding= "UTF-8"? ><beans xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"       xmlns= "Http://www.springframework.org/schema/beans"      xmlns:context= "http://www.springframework.org/schema/ Context "      xsi:schemalocation=" Http://www.springframework.org/schema/beans/         http Www.springframework.org/schema/beans/spring-beans-4.2.xsd        Http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context-4.2.xsd "    default-autowire=" Bytype ">        <bean id= "Zoo" class= "Com.xrq.bean.Zoo" >        <property name= "Tiger" ref= "Tiger"/>        < Property Name= "Monkey" ref= "monkey"/>    </bean>        <bean id= "Tiger" class= "Com.xrq.domain.Tiger"/ >    <bean id= "monkey" class= "Com.xrq.domain.Monkey"/>    </beans>

are very familiar with, right when review again.

@Autowired

@Autowired, as the name implies, is automatic assembly, which is intended to eliminate the property in the Getter/setter and Bean properties of code Java code. Of course, getter looks at individual needs and should be retained if the private attribute needs to be provided externally.

So, introducing @autowired annotations, let's look at how the spring configuration file is written:

1 <?xml version= "1.0" encoding= "UTF-8"?> 2 <beans xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"    3     xmlns= "Http://www.springframework.org/schema/beans"   4     xmlns:context= "/http Www.springframework.org/schema/context "   5     xsi:schemalocation=" http://www.springframework.org/schema/ Beans  6         http://www.springframework.org/schema/beans/spring-beans-4.2.xsd 7/         http Www.springframework.org/schema/context 8         http://www.springframework.org/schema/context/ Spring-context-4.2.xsd "> 9     <context:component-scan base-package=" Com.xrq "/>11     12     <bean id= "Zoo" class= "Com.xrq.bean.Zoo"/>13     <bean id= "Tiger" class= "Com.xrq.domain.Tiger"/>     <bean id= "monkey" class= "Com.xrq.domain.Monkey"/>15     </beans>

Note the 10th line, use must tell spring I want to use annotations, tell the way there are many, <context:component-scan base-package= "xxx"/> is one of the simplest, Spring will automatically scan the annotations under the XXX path.

See line 12th, the original zoo inside should inject two attributes Tiger, monkey, now do not need to inject. Look again, Zoo.java is also very convenient, the getter/setter can be removed:

public class zoo{    @Autowired    private Tiger Tiger;        @Autowired    private Monkey Monkey;        Public String toString ()    {        return tiger + "\ n" + Monkey;    }}

The @autowired annotation here means that when Spring discovers the @autowired annotation, it automatically finds the bean in the code context that matches (by default, the type match) and automatically injects it to the appropriate place.

One of the more detailed questions is, what if there are two property,zoo.java inside the bean with the attribute getter/setter removed and the two properties annotated with the @autowired annotation? The answer is that spring will look for the getter/setter of these two properties in the Zoo.java of XML precedence, resulting in the initialization of the bean error.

OK, assuming that at this point I take the. xml file 13 lines, 14 rows of two lines to remove, and then run, will throw an exception:

Exception in thread "main" Org.springframework.beans.factory.BeanCreationException:Error creating Beans with Name ' Zoo ': Injection of autowired dependencies failed; Nested exception is org.springframework.beans.factory.BeanCreationException:Could not Autowire field:private Com.xrq.domain.Tiger Com.xrq.bean.Zoo.ttiger; Nested exception is Org.springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type [ Com.xrq.domain.Tiger] found for dependency:expected at least 1 beans which qualifies as Autowire candidate for this depend Ency. Dependency annotations: {@org. springframework.beans.factory.annotation.Autowired (Required=true)} at Org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues ( autowiredannotationbeanpostprocessor.java:334) at Org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean ( abstractautowirecapablebeanfactory.java:1214) at Org.springframework.beans.factoRy.support.AbstractAutowireCapableBeanFactory.doCreateBean (abstractautowirecapablebeanfactory.java:543) at Org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean ( abstractautowirecapablebeanfactory.java:482) at org.springframework.beans.factory.support.abstractbeanfactory$1. GetObject (abstractbeanfactory.java:305) at Org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton ( defaultsingletonbeanregistry.java:230) at Org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean (abstractbeanfactory.java:301) at Org.springframework.beans.factory.support.AbstractBeanFactory.getBean (abstractbeanfactory.java:196) at Org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons ( defaultlistablebeanfactory.java:772) at Org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization ( abstractapplicationcontext.java:835) at Org.springframework.conText.support.AbstractApplicationContext.refresh (abstractapplicationcontext.java:537) at Org.springframework.context.support.classpathxmlapplicationcontext.<init> ( classpathxmlapplicationcontext.java:139) at Org.springframework.context.support.ClassPathXmlApplicationContext. <init> (classpathxmlapplicationcontext.java:83) at Com.xrq.test.MyTest.main (mytest.java:13) caused by: Org.springframework.beans.factory.BeanCreationException:Could not Autowire field:private Com.xrq.domain.Tiger Com.xrq.bean.Zoo.ttiger; Nested exception is Org.springframework.beans.factory.NoSuchBeanDefinitionException:No qualifying bean of type [ Com.xrq.domain.Tiger] found for dependency:expected at least 1 beans which qualifies as Autowire candidate for this depend Ency. Dependency annotations: {@org. springframework.beans.factory.annotation.Autowired (Required=true)} at Org.springframework.beans.factory.annotation.autowiredannotationbeanpostprocessor$autowiredfieldelement.inject (Autowiredannotationbeanpostprocessor.java:571) at Org.springframework.beans.factory.annotation.InjectionMetadata.inject ( injectionmetadata.java:88) at Org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues ( autowiredannotationbeanpostprocessor.java:331) ... morecaused by:org.springframework.beans.factory.NoSuchBeanDefinitionException:No Qualifying Bean of type [ Com.xrq.domain.Tiger] found for dependency:expected at least 1 beans which qualifies as Autowire candidate for this depend Ency. Dependency annotations: {@org. springframework.beans.factory.annotation.Autowired (Required=true)} at Org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException ( defaultlistablebeanfactory.java:1373) at Org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency ( defaultlistablebeanfactory.java:1119) at Org.springframework.beans.factory.support.DefaultListableBeanFactory.resOlvedependency (defaultlistablebeanfactory.java:1014) at Org.springframework.beans.factory.annotation.autowiredannotationbeanpostprocessor$autowiredfieldelement.inject (autowiredannotationbeanpostprocessor.java:543) ... More

Because, @Autowired annotations are going to look for a bean,tiger and monkey bean definition is removed, nature is not a bean, spring container can not find also very good understanding. So, if the property can't be found I don't want the spring container to throw an exception, and that is to show null, OK? Yes, in fact, the exception information is also given a hint, that is, the required attribute of the @autowired annotation is set to false:

public class zoo{    @Autowired (required = false)    private Tiger Tiger;        @Autowired (required = false)    private Monkey Monkey;        Public String toString ()    {        return tiger + "\ n" + Monkey;    }}

At this point, the tiger, monkey two attributes are not found, and the spring container no longer throws an exception but considers the two properties null.

@Autowired Interface Injection

The above is relatively simple, we simply inject a Java class, then if there is an interface, there are multiple implementations, the Bean refers to the interface name, and how to do it? For example, there is a car interface:

Public interface car{Public    String carname ();}

Two implementation classes BMW and Benz:

@Servicepublic class BMW implements car{public    String carname ()    {        return "BMW Car";    }}
@Servicepublic class Benz implements car{public    String carname ()    {        return "Benz Car";    }}

Write a carfactory, quote car:

@Servicepublic class carfactory{    @Autowired    private car car;        Public String toString ()    {        return car.carname ();    }}

Needless to say, it must be an error, the car interface has two implementation classes, and spring does not know which implementation class should be referenced. There are usually two solutions to this situation:

1, delete one of the implementation class, spring will automatically go to base-package under the car interface to find the implementation class, found that the car interface only one implementation class, will directly refer to this implementation class

2, the implementation of the class is that there are more than what to do? You can use @qualifier annotations at this time:

@Servicepublic class carfactory{    @Autowired    @Qualifier ("BMW")    private car car;        Public String toString ()    {        return car.carname ();    }}

Note that the @qualifier annotation inside the parentheses should be the class name of the car interface implementation class , I tried before the time I thought it was the name of the Bean, so wrote "BMW", the result has been an error.

@Resource

Put @resource annotations under @autowired said, because they function very similar, this is simply said, the example after the @resource and @autowired the difference. First look at the @resource, directly write Zoo.java:

@Servicepublic class zoo{    @Resource (name = "Tiger")    private tiger Tiger;        @Resource (type = monkey.class)    private Monkey Monkey;        Public String toString ()    {        return tiger + "\ n" + Monkey;    }}

This is a detailed usage, say the assembly order of the @resource:

1, @Resource nothing behind, by default by the Name property to match the bean, can not find and then press the type to match

2. The name or type is specified to match the bean according to the specified type

3, the name and type are specified to match the bean according to the specified name and type, any mismatch will be an error

Then, differentiate between the two annotations of @autowired and @resource:

1, @Autowired By default, the Bean match Bytype way, @Resource by default bean matching in the way of byname

2, @Autowired is the note of spring, @Resource is the note of the Java EE, this look at the import annotations when the package name of the two annotations is clear.

Spring belongs to third parties, and the Java EE is its own thing, so it is recommended to use @resource annotations to reduce the coupling between the code and spring.

@Service

In this example, you can continue simplifying, because there are 12 rows of ~14 three beans in the spring configuration file, and the next simplification is to remove the three beans, so that there is only one automatically scanned label in the Spring config file. Enhance the cohesion of Java code and further reduce configuration files.

To continue simplifying, you can use @service. First look at the configuration file, of course, it is all deleted:

<?xml version= "1.0" encoding= "UTF-8"? ><beans xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"       xmlns= "Http://www.springframework.org/schema/beans"      xmlns:context= "http://www.springframework.org/schema/ Context "      xsi:schemalocation=" Http://www.springframework.org/schema/beans/         http Www.springframework.org/schema/beans/spring-beans-4.2.xsd        Http://www.springframework.org/schema/context        http://www.springframework.org/schema/context/spring-context-4.2.xsd ">        <context:component-scan Base-package= "Com.xrq"/>    </beans>

Does it feel good? At least, I think so. OK, take Zoo.java for example, the rest of Monkey.java and Tiger.java are the same:

@Servicepublic class zoo{    @Autowired    private Tiger Ttiger;        @Autowired    private Monkey mmonkey;        Public String toString ()    {        return ttiger + "\ n" + Mmonkey;    }}

In this way, the form of Zoo.java in the spring container is the "zoo", which means that the Zoo.java can be obtained through the ApplicationContext Getbean ("Zoo") method. @Service annotations, two things have actually been done:

1. It is important to declare that Zoo.java is a bean, because Zoo.java is a bean and other classes can use @autowired to automatically inject the zoo as a member variable

2, Zoo.java in the bean ID is "Zoo", that is, the class name and the first letter lowercase

If, I do not want to do in this form, just want to let Zoo.java in the spring container name called "Zoo", can be:

@Service @scope ("prototype") public class zoo{    @Autowired    private Monkey Monkey;    @Autowired    private Tiger Tiger;        Public String toString ()    {        return "Monkeyname:" + Monkey + "\ntigername:" + Tiger;    }}

In this way, you can get Zoo.java by ApplicationContext's Getbean ("Zoo") method.

Here I add a @scope annotation, should be well understood. Because the default bean generated by spring is singleton, if I don't want to use a singleton, the XML file can be configured with the scope property inside the bean. Annotations are the same, the configuration of @scope, the default is "Singleton" is a singleton, "prototype" means that the prototype is a new one each time.

Additional details

Finally, add one more detail that I found. If animal package has tiger, domain package also has tiger, they both add @service annotation, then in Zoo.java even if I want to refer to the tiger under the domain package, the program will still error when running.

Think, actually this is very good understanding, two tiger all use @service annotation callout, mean two Bean's name is "Tiger", then I in Zoo.java automatically assemble which tiger? Ambiguous, therefore, the spring container throws an beandefinitionstoreexception exception, caused by:

caused by:org.springframework.context.annotation.conflictingbeandefinitionexception:annotation-specified bean Name ' Monkey ' for Bean class [Com.xrq.domain.Monkey] conflicts with existing, non-compatible bean definition of same name and class [Com.xrq.animal.Monkey]

Spring5: @Autowired annotations, @Resource annotations, and @service annotations

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.