欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Spring注解--@Autowired、@Resource和@Service

 更新時(shí)間:2017年05月02日 14:11:45   作者:五月的倉(cāng)頡  
本篇文章主要介紹最重要的三個(gè)Spring注解,也就是@Autowired、@Resource和@Service,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧

什么是注解

傳統(tǒng)的Spring做法是使用.xml文件來(lái)對(duì)bean進(jìn)行注入或者是配置aop、事物,這么做有兩個(gè)缺點(diǎn):

1、如果所有的內(nèi)容都配置在.xml文件中,那么.xml文件將會(huì)十分龐大;如果按需求分開(kāi).xml文件,那么.xml文件又會(huì)非常多。總之這將導(dǎo)致配置文件的可讀性與可維護(hù)性變得很低

2、在開(kāi)發(fā)中在.java文件和.xml文件之間不斷切換,是一件麻煩的事,同時(shí)這種思維上的不連貫也會(huì)降低開(kāi)發(fā)的效率

為了解決這兩個(gè)問(wèn)題,Spring引入了注解,通過(guò)"@XXX"的方式,讓注解與Java Bean緊密結(jié)合,既大大減少了配置文件的體積,又增加了Java Bean的可讀性與內(nèi)聚性。

本篇文章,講講最重要的三個(gè)Spring注解,也就是@Autowired、@Resource和@Service,希望能通過(guò)有限的篇幅說(shuō)清楚這三個(gè)注解的用法。

不使用注解

先看一個(gè)不使用注解的Spring示例,在這個(gè)示例的基礎(chǔ)上,改成注解版本的,這樣也能看出使用與不使用注解之間的區(qū)別,先定義一個(gè)老虎:

public class Tiger
{
 private String tigerName = "TigerKing";
 
 public String toString()
 {
  return "TigerName:" + tigerName;
 }
}

再定義一個(gè)猴子:

public class Monkey
{
 private String monkeyName = "MonkeyKing";
 
 public String toString()
 {
  return "MonkeyName:" + monkeyName;
 }
}

定義一個(gè)動(dòng)物園:

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

spring的配置文件這么寫(xiě):

<?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>

都很熟悉,權(quán)當(dāng)復(fù)習(xí)一遍了。

@Autowired

@Autowired顧名思義,就是自動(dòng)裝配,其作用是為了消除代碼Java代碼里面的getter/setter與bean屬性中的property。當(dāng)然,getter看個(gè)人需求,如果私有屬性需要對(duì)外提供的話,應(yīng)當(dāng)予以保留。

因此,引入@Autowired注解,先看一下spring配置文件怎么寫(xiě):

<?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" />

 <bean id="zoo" class="com.xrq.bean.Zoo" />
 <bean id="tiger" class="com.xrq.domain.Tiger" />
 <bean id="monkey" class="com.xrq.domain.Monkey" />
</beans>

注意第10行,使用必須告訴spring一下我要使用注解了,告訴的方式有很多,<context:component-scan base-package="xxx" />是一種最簡(jiǎn)單的,spring會(huì)自動(dòng)掃描xxx路徑下的注解。

看到第12行,原來(lái)zoo里面應(yīng)當(dāng)注入兩個(gè)屬性tiger、monkey,現(xiàn)在不需要注入了。再看下,Zoo.java也很方便,把getter/setter都可以去掉:

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

這里@Autowired注解的意思就是,當(dāng)Spring發(fā)現(xiàn)@Autowired注解時(shí),將自動(dòng)在代碼上下文中找到和其匹配(默認(rèn)是類型匹配)的Bean,并自動(dòng)注入到相應(yīng)的地方去。

有一個(gè)細(xì)節(jié)性的問(wèn)題是,假如bean里面有兩個(gè)property,Zoo.java里面又去掉了屬性的getter/setter并使用@Autowired注解標(biāo)注這兩個(gè)屬性那會(huì)怎么樣?答案是Spring會(huì)按照xml優(yōu)先的原則去Zoo.java中尋找這兩個(gè)屬性的getter/setter,導(dǎo)致的結(jié)果就是初始化bean報(bào)錯(cuò)。

OK,假設(shè)此時(shí)我把.xml文件的13行、14行兩行給去掉,再運(yùn)行,會(huì)拋出異常:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean 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 bean which qualifies as autowire candidate for this dependency. 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 bean which qualifies as autowire candidate for this dependency. 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)
 ... 13 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.xrq.domain.Tiger] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. 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)
 ... 15 more

因?yàn)椋珸Autowired注解要去尋找的是一個(gè)Bean,Tiger和Monkey的Bean定義都給去掉了,自然就不是一個(gè)Bean了,Spring容器找不到也很好理解。那么,如果屬性找不到我不想讓Spring容器拋出異常,而就是顯示null,可以嗎?可以的,其實(shí)異常信息里面也給出了提示了,就是將@Autowired注解的required屬性設(shè)置為false即可:

public class Zoo
{
 @Autowired(required = false)
 private Tiger tiger;

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

此時(shí),找不到tiger、monkey兩個(gè)屬性,Spring容器不再拋出異而是認(rèn)為這兩個(gè)屬性為null。

@Autowired接口注入

上面的比較簡(jiǎn)單,我們只是簡(jiǎn)單注入一個(gè)Java類,那么如果有一個(gè)接口,有多個(gè)實(shí)現(xiàn),Bean里引用的是接口名,又該怎么做呢?比如有一個(gè)Car接口:

public interface Car
{
 public String carName();
}

兩個(gè)實(shí)現(xiàn)類BMW和Benz:

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

寫(xiě)一個(gè)CarFactory,引用Car:

@Service
public class CarFactory
{
 @Autowired
 private Car car;
 public String toString()
 {
  return car.carName();
 }
}

不用說(shuō),一定是報(bào)錯(cuò)的,Car接口有兩個(gè)實(shí)現(xiàn)類,Spring并不知道應(yīng)當(dāng)引用哪個(gè)實(shí)現(xiàn)類。這種情況通常有兩個(gè)解決辦法:

1、刪除其中一個(gè)實(shí)現(xiàn)類,Spring會(huì)自動(dòng)去base-package下尋找Car接口的實(shí)現(xiàn)類,發(fā)現(xiàn)Car接口只有一個(gè)實(shí)現(xiàn)類,便會(huì)直接引用這個(gè)實(shí)現(xiàn)類

2、實(shí)現(xiàn)類就是有多個(gè)該怎么辦?此時(shí)可以使用@Qualifier注解:

@Service
public class CarFactory
{
 @Autowired
 @Qualifier("BMW")
 private Car car;
 
 public String toString()
 {
  return car.carName();
 }
}

注意@Qualifier注解括號(hào)里面的應(yīng)當(dāng)是Car接口實(shí)現(xiàn)類的類名,我之前試的時(shí)候一直以為是bean的名字,所以寫(xiě)了"bMW",結(jié)果一直報(bào)錯(cuò)。

@Resource

把@Resource注解放在@Autowired下面說(shuō),是因?yàn)樗鼈冏饔梅浅O嗨?,這個(gè)就簡(jiǎn)單說(shuō)了,例子過(guò)后點(diǎn)明一下@Resource和@Autowired的區(qū)別。先看一下@Resource,直接寫(xiě)Zoo.java了:

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

這是詳細(xì)一些的用法,說(shuō)一下@Resource的裝配順序:

1、@Resource后面沒(méi)有任何內(nèi)容,默認(rèn)通過(guò)name屬性去匹配bean,找不到再按type去匹配

2、指定了name或者type則根據(jù)指定的類型去匹配bean

3、指定了name和type則根據(jù)指定的name和type去匹配bean,任何一個(gè)不匹配都將報(bào)錯(cuò)

然后,區(qū)分一下@Autowired和@Resource兩個(gè)注解的區(qū)別:

1、@Autowired默認(rèn)按照byType方式進(jìn)行bean匹配,@Resource默認(rèn)按照byName方式進(jìn)行bean匹配

2、@Autowired是Spring的注解,@Resource是J2EE的注解,這個(gè)看一下導(dǎo)入注解的時(shí)候這兩個(gè)注解的包名就一清二楚了

Spring屬于第三方的,J2EE是Java自己的東西,因此,建議使用@Resource注解,以減少代碼和Spring之間的耦合。

@Service

上面這個(gè)例子,還可以繼續(xù)簡(jiǎn)化,因?yàn)閟pring的配置文件里面還有12行~14行三個(gè)bean,下一步的簡(jiǎn)化是把這三個(gè)bean也給去掉,使得spring配置文件里面只有一個(gè)自動(dòng)掃描的標(biāo)簽,增強(qiáng)Java代碼的內(nèi)聚性并進(jìn)一步減少配置文件。

要繼續(xù)簡(jiǎn)化,可以使用@Service。先看一下配置文件,當(dāng)然是全部刪除了:

<?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>

是不是感覺(jué)很爽?起碼我覺(jué)得是的。OK,下面以Zoo.java為例,其余的Monkey.java和Tiger.java都一樣:

@Service
public class Zoo
{
 @Autowired
 private Tiger ttiger;
 @Autowired
 private Monkey mmonkey;
 public String toString()
 {
  return ttiger + "\n" + mmonkey;
 }
}

這樣,Zoo.java在Spring容器中存在的形式就是"zoo",即可以通過(guò)ApplicationContext的getBean("zoo")方法來(lái)得到Zoo.java。@Service注解,其實(shí)做了兩件事情:

1、聲明Zoo.java是一個(gè)bean,這點(diǎn)很重要,因?yàn)閆oo.java是一個(gè)bean,其他的類才可以使用@Autowired將Zoo作為一個(gè)成員變量自動(dòng)注入

2、Zoo.java在bean中的id是"zoo",即類名且首字母小寫(xiě)

如果,我不想用這種形式怎么辦,就想讓Zoo.java在Spring容器中的名字叫做"Zoo",可以的:

@Service
@Scope("prototype")
public class Zoo
{
 @Autowired
 private Monkey monkey;
 @Autowired
 private Tiger tiger;
 public String toString()
 {
  return "MonkeyName:" + monkey + "\nTigerName:" + tiger;
 }
}

這樣,就可以通過(guò)ApplicationContext的getBean("zoo")方法來(lái)得到Zoo.java了。

這里我還多加了一個(gè)@Scope注解,應(yīng)該很好理解。因?yàn)镾pring默認(rèn)產(chǎn)生的bean是單例的,假如我不想使用單例怎么辦,xml文件里面可以在bean里面配置scope屬性。注解也是一樣,配置@Scope即可,默認(rèn)是"singleton"即單例,"prototype"表示原型即每次都會(huì)new一個(gè)新的出來(lái)。

補(bǔ)充細(xì)節(jié)

最后再補(bǔ)充一個(gè)我發(fā)現(xiàn)的細(xì)節(jié)。假如animal包下有Tiger、domain包下也有Tiger,它們二者都加了@Service注解,那么在Zoo.java中即使明確表示我要引用的是domain包下的Tiger,程序運(yùn)行的時(shí)候依然會(huì)報(bào)錯(cuò)。

細(xì)想,其實(shí)這很好理解,兩個(gè)Tiger都使用@Service注解標(biāo)注,意味著兩個(gè)Bean的名字都是"tiger",那么我在Zoo.java中自動(dòng)裝配的是哪個(gè)Tiger呢?不明確,因此,Spring容器會(huì)拋出BeanDefinitionStoreException異常,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]

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!

相關(guān)文章

  • 解決Maven打包只有幾十K,運(yùn)行報(bào)錯(cuò)no main manifest attribute問(wèn)題

    解決Maven打包只有幾十K,運(yùn)行報(bào)錯(cuò)no main manifest attribute

    這篇文章主要介紹了解決Maven打包只有幾十K,運(yùn)行報(bào)錯(cuò)no main manifest attribute問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • 一篇文章帶你了解Java SpringMVC返回null

    一篇文章帶你了解Java SpringMVC返回null

    這篇文章主要介紹了Spring MVC返回null,文中講的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-10-10
  • java實(shí)現(xiàn)登錄之后抓取數(shù)據(jù)

    java實(shí)現(xiàn)登錄之后抓取數(shù)據(jù)

    這篇文章給大家分享了用JAVA實(shí)現(xiàn)在登陸以后抓取網(wǎng)站的數(shù)據(jù)的相關(guān)知識(shí),有興趣的朋友可以測(cè)試參考下。
    2018-07-07
  • Java實(shí)現(xiàn)驗(yàn)證碼具體代碼(圖片、漢字)

    Java實(shí)現(xiàn)驗(yàn)證碼具體代碼(圖片、漢字)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)驗(yàn)證碼具體代碼,包括圖片驗(yàn)證碼、漢字驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-01-01
  • Java中Properties配置類用法詳解

    Java中Properties配置類用法詳解

    所謂的配置文件問(wèn)題,是指我們?cè)陂_(kāi)發(fā)時(shí),經(jīng)常需要讀取和修改一些配置信息,比如數(shù)據(jù)庫(kù)、消息隊(duì)列、Nginx、Web服務(wù)器等的配置,為了便于修改這些信息,我們可以采用Properties配置類,本文給大家講一下Properties配置類是怎么回事,以及怎么使用
    2023-06-06
  • 在SpringBoot中該如何配置攔截器

    在SpringBoot中該如何配置攔截器

    今天給大家?guī)?lái)的是關(guān)于SpringBoot的相關(guān)知識(shí),文章圍繞在SpringBoot中該如何配置攔截器展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • RocketMQ設(shè)計(jì)之同步刷盤(pán)

    RocketMQ設(shè)計(jì)之同步刷盤(pán)

    這篇文章主要介紹了RocketMQ設(shè)計(jì)之同步刷盤(pán),文章主要通過(guò)CommitLog的handleDiskFlush方法展開(kāi)全文內(nèi)容,實(shí)現(xiàn)同步刷盤(pán),下面文章詳細(xì)介紹,需要的小伙伴可以參考一下
    2022-03-03
  • Spring SpringMVC,Spring整合MyBatis 事務(wù)配置的詳細(xì)流程

    Spring SpringMVC,Spring整合MyBatis 事務(wù)配置的詳細(xì)流程

    這篇文章給大家介紹SSM整合詳細(xì)流程步驟 Spring SpringMVC,Spring整合MyBatis 事務(wù)配置,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-10-10
  • Java中類的初始化和實(shí)例化區(qū)別詳解

    Java中類的初始化和實(shí)例化區(qū)別詳解

    這篇文章主要介紹了Java中類的初始化和實(shí)例化區(qū)別詳解,類的初始化<BR>是完成程序執(zhí)行前的準(zhǔn)備工作,類的實(shí)例化(實(shí)例化對(duì)象)是指創(chuàng)建一個(gè)對(duì)象的過(guò)程,需要的朋友可以參考下
    2023-08-08

最新評(píng)論