1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Spring系列之Spring常用注解總結(jié)

        共 22586字,需瀏覽 46分鐘

         ·

        2020-09-17 10:17


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


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


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


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

        不使用注解:


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


        package?com.spring.model;

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


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


        package?com.spring.model;

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

        }


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


        package?com.spring.model;

        public?class?Zoo?{
        ????private?Tiger tiger;
        ????private?Monkey monkey;
        ????
        ????public?Tiger getTiger()?{
        ????????return?tiger;
        ????}
        ????public?void?setTiger(Tiger tiger)?{
        ????????this.tiger = tiger;
        ????}
        ????public?Monkey getMonkey()?{
        ????????return?monkey;
        ????}
        ????public?void?setMonkey(Monkey monkey)?{
        ????????this.monkey = monkey;
        ????}
        ????
        ????public?String toString(){
        ????????return?tiger + "\n"?+ monkey;
        ????}
        ????
        }


        spring的配置文件這么寫:


        xml version="1.0"?encoding="UTF-8"?>
        <beans
        ????xmlns="http://www.springframework.org/schema/beans"
        ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        ????xmlns:p="http://www.springframework.org/schema/p"
        ????xmlns:context="http://www.springframework.org/schema/context"
        ????xsi:schemaLocation="http://www.springframework.org/schema/beans
        ????http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        ????http://www.springframework.org/schema/context
        ????http://www.springframework.org/schema/context/spring-context-3.0.xsd
        ????"
        >

        ????
        ?????<bean?id="zoo"?class="com.spring.model.Zoo"?>
        ????????<property?name="tiger"?ref="tiger"?/>
        ????????<property?name="monkey"?ref="monkey"?/>
        ????bean>

        ????
        ????<bean?id="tiger"?class="com.spring.model.Tiger"?/>
        ????<bean?id="monkey"?class="com.spring.model.Monkey"?/>

        beans>


        測(cè)試方法:


        public?class?TestAnnotation?{
        ????/**
        ?????* 不使用注解
        ?????*/

        ????@Test
        ????public?void?test()
        {
        ????????//讀取配置文件
        ????????ApplicationContext ctx=new?ClassPathXmlApplicationContext("applicationContext2.xml");
        ????????Zoo zoo=(Zoo) ctx.getBean("zoo");
        ????????System.out.println(zoo.toString());
        ????}
        }


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


        1、@Autowired


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


        @Autowired默認(rèn)按類型匹配的方式,在容器查找匹配的Bean,當(dāng)有且僅有一個(gè)匹配的Bean時(shí),Spring將其注入@Autowired標(biāo)注的變量中。


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


        xml version="1.0"?encoding="UTF-8"?>
        <beans
        ????xmlns="http://www.springframework.org/schema/beans"
        ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        ????xmlns:p="http://www.springframework.org/schema/p"
        ????xmlns:context="http://www.springframework.org/schema/context"
        ????xsi:schemaLocation="http://www.springframework.org/schema/beans
        ????http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        ????http://www.springframework.org/schema/context
        ????http://www.springframework.org/schema/context/spring-context-3.0.xsd
        ????"
        >


        ????<context:component-scan?base-package="com.spring"?/>

        ????<bean?id="zoo"?class="com.spring.model.Zoo"?/>
        ????<bean?id="tiger"?class="com.spring.model.Tiger"?/>
        ????<bean?id="monkey"?class="com.spring.model.Monkey"?/>

        beans>


        注意第13行,使用必須告訴spring一下我要使用注解了,告訴的方式有很多,是一種最簡(jiǎn)單的,spring會(huì)自動(dòng)掃描xxx路徑下的注解。


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


        package?com.spring.model;

        import?org.springframework.beans.factory.annotation.Autowired;

        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é)性的問題是,假如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文件的16行、17行兩行給去掉,再運(yùn)行,會(huì)拋出異常:


        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.spring.model.Tiger com.spring.model.Zoo.tiger; nested exception is?org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.spring.model.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:285)
        ????at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
        ????at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
        ????at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
        ????at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
        ????at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        ????at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
        ????at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
        ????at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
        ????at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
        ????at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
        ????at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
        ????at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
        ????at com.spring.test.TestAnnotation.test(TestAnnotation.java:16)
        ????at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        ????at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        ????at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        ????at java.lang.reflect.Method.invoke(Method.java:597)
        ????at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
        ????at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
        ????at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
        ????at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
        ????at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
        ????at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
        ????at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
        ????at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
        ????at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
        ????at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
        ????at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
        ????at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
        ????at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
        ????at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
        ????at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        ????at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
        ????at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
        ????at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
        ????at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
        Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private?com.spring.model.Tiger com.spring.model.Zoo.tiger; nested exception is?org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.spring.model.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:502)
        ????at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
        ????at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
        ????... 36?more
        Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.spring.model.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:920)
        ????at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:789)
        ????at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
        ????at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
        ????... 38?more

        復(fù)制代碼


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


        package?com.spring.model;

        import?org.springframework.beans.factory.annotation.Autowired;

        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。


        2、Qualifier(指定注入Bean的名稱)


        如果容器中有一個(gè)以上匹配的Bean,則可以通過@Qualifier注解限定Bean的名稱,看下面的例子:


        定義一個(gè)Car接口:


        package?com.spring.service;

        public?interface?ICar?{
        ????
        ????public?String getCarName();
        }


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


        package?com.spring.service.impl;

        import?com.spring.service.ICar;

        public?class?BMWCar?implements?ICar{
        ????
        ????public?String getCarName(){
        ????????return?"BMW car";
        ????}
        }


        package?com.spring.service.impl;

        import?com.spring.service.ICar;

        public?class?BenzCar?implements?ICar{
        ????
        ????public?String getCarName(){
        ????????return?"Benz car";
        ????}
        }


        再寫一個(gè)CarFactory,引用car(這里先不用@Qualifier注解):


        package?com.spring.model;

        import?org.springframework.beans.factory.annotation.Autowired;

        import?com.spring.service.ICar;

        public?class?CarFactory?{
        ????
        ????@Autowired
        ????private?ICar car;
        ????
        ????public?String toString(){
        ????????return?car.getCarName();
        ????}
        ????
        }


        配置文件:


        xml version="1.0"?encoding="UTF-8"?>
        <beans
        ????xmlns="http://www.springframework.org/schema/beans"
        ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        ????xmlns:p="http://www.springframework.org/schema/p"
        ????xmlns:context="http://www.springframework.org/schema/context"
        ????xsi:schemaLocation="http://www.springframework.org/schema/beans
        ????http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        ????http://www.springframework.org/schema/context
        ????http://www.springframework.org/schema/context/spring-context-3.0.xsd
        ????"
        >

        ????
        ????<context:component-scan?base-package="com.spring"?/>
        ????
        ????
        ????<bean?id="carFactory"?class="com.spring.model.CarFactory"?/>
        ????<bean?id="bmwCar"?class="com.spring.service.impl.BMWCar"?/>
        ????<bean?id="benz"?class="com.spring.service.impl.BenzCar"?/>
        ????
        beans>


        測(cè)試方法:


        /**
        ?* Autowired注解配合Qualifier注解
        ?*/

        @Test
        public?void?test1()
        {
        ????//讀取配置文件
        ????ApplicationContext ctx=new?ClassPathXmlApplicationContext("applicationContext2.xml");
        ????CarFactory carFactory=(CarFactory) ctx.getBean("carFactory");
        ????System.out.println(carFactory.toString());
        }


        運(yùn)行一下,不用說,一定是報(bào)錯(cuò)的,Car接口有兩個(gè)實(shí)現(xiàn)類,Spring并不知道應(yīng)當(dāng)引用哪個(gè)實(shí)現(xiàn)類。


        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'carFactory': Injection of autowired dependencies failed; nested exception is?org.springframework.beans.factory.BeanCreationException: Could not autowire field: private?com.spring.service.ICar com.spring.model.CarFactory.car; nested exception is?org.springframework.beans.factory.NoSuchBeanDefinitionException:No unique bean of type [com.spring.service.ICar] is?defined: expected single matching bean but found 2: [bmwCar, benz]
        ????at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
        ????at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
        ????at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
        ????at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
        ????at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
        ????at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
        ????at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
        ????at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
        ????at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
        ????at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
        ????at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
        ????at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
        ????at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
        ????at com.spring.test.TestAnnotation.test1(TestAnnotation.java:25)
        ????at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        ????at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        ????at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        ????at java.lang.reflect.Method.invoke(Method.java:597)
        ????at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
        ????at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
        ????at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
        ????at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
        ????at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
        ????at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
        ????at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
        ????at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
        ????at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
        ????at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
        ????at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
        ????at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
        ????at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
        ????at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
        ????at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
        ????at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
        ????at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
        ????at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
        ????at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
        Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private?com.spring.service.ICar com.spring.model.CarFactory.car; nested exception is?org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.spring.service.ICar] is?defined: expected single matching bean but found 2: [bmwCar, benz]
        ????at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502)
        ????at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
        ????at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282)
        ????... 36?more
        Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.spring.service.ICar] is?defined: expected single matching bean but found 2: [bmwCar, benz]
        ????at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:796)
        ????at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703)
        ????at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474)
        ????... 38?more


        出現(xiàn)這種情況通常有兩種解決辦法:


        (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注解來指定Bean的名稱:


        package?com.spring.model;

        import?org.springframework.beans.factory.annotation.Autowired;
        import?org.springframework.beans.factory.annotation.Qualifier;

        import?com.spring.service.ICar;

        public?class?CarFactory?{
        ????
        ????@Autowired
        ????@Qualifier("bmwCar")
        ????private ICar car;
        ????
        ????public?String?toString(){
        ????????return?car.getCarName();
        ????}
        ????
        }


        此處會(huì)注入名為"bmwCar"的Bean。


        3、Resource


        @Resource注解與@Autowired注解作用非常相似,這個(gè)就簡(jiǎn)單說了,看例子:


        package?com.spring.model;

        import?javax.annotation.Resource;

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


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


        (1)、@Resource后面沒有任何內(nèi)容,默認(rèn)通過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之間的耦合。


        4、Service


        上面這個(gè)例子,還可以繼續(xù)簡(jiǎn)化,因?yàn)閟pring的配置文件里面還有15行~17行三個(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)然是全部刪除了:


        version="1.0"?encoding="UTF-8"?>
        ????xmlns="http://www.springframework.org/schema/beans"
        ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        ????xmlns:p="http://www.springframework.org/schema/p"
        ????xmlns:context="http://www.springframework.org/schema/context"
        ????xsi:schemaLocation="http://www.springframework.org/schema/beans
        ????http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        ????http://www.springframework.org/schema/context
        ????http://www.springframework.org/schema/context/spring-context-3.0.xsd
        ????">
        ????
        ????t:component-scan base-package="com.spring"?/>
        ????


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


        package?com.spring.model;

        import?org.springframework.beans.factory.annotation.Autowired;
        import?org.springframework.stereotype.Service;

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


        這樣,Zoo.java在Spring容器中存在的形式就是"zoo",即可以通過ApplicationContext的getBean("zoo")方法來得到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",即類名且首字母小寫。


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


        package?com.spring.model;

        import?org.springframework.beans.factory.annotation.Autowired;
        import?org.springframework.context.annotation.Scope;
        import?org.springframework.stereotype.Service;

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


        這樣,就可以通過ApplicationContext的getBean("Zoo")方法來得到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è)新的出來。


        使用注解來構(gòu)造IoC容器


        用注解來向Spring容器注冊(cè)Bean。需要在applicationContext.xml中注冊(cè)


        如:在base-package指明一個(gè)包


        t:component-scan base-package="cn.gacl.java"/>


        表明cn.gacl.java包及其子包中,如果某個(gè)類的頭上帶有特定的注解【@Component/@Repository/@Service/@Controller】,就會(huì)將這個(gè)對(duì)象作為Bean注冊(cè)進(jìn)Spring容器。也可以在中指定多個(gè)包,如:


        t:component-scan base-package="cn.gacl.dao.impl,cn.gacl.service.impl,cn.gacl.action"/>


        多個(gè)包逗號(hào)隔開。


        1、@Component


        @Component是所有受Spring 管理組件的通用形式,@Component注解可以放在類的頭上,@Component不推薦使用。


        2、@Controller


        @Controller對(duì)應(yīng)表現(xiàn)層的Bean,也就是Action,例如:


        @Controller
        @Scope("prototype")
        public class UserAction extends BaseAction{
        ?……
        }


        使用@Controller注解標(biāo)識(shí)UserAction之后,就表示要把UserAction交給Spring容器管理,Spring容器中會(huì)存在一個(gè)名字為"userAction"action,這個(gè)名字是根據(jù)UserAction類名來取的。注意:如果@Controller不指定其value【@Controller】,則默認(rèn)的bean名字為這個(gè)類的類名首字母小寫如果指定value【@Controller(value="UserAction")】或者【@Controller("UserAction")】,則使用value作為bean的名字。


        這里的UserAction還使用了@Scope注解,@Scope("prototype")表示將Action的范圍聲明為原型,可以利用容器的scope="prototype"來保證每一個(gè)請(qǐng)求有一個(gè)單獨(dú)的Action來處理,避免strutsAction的線程安全問題。spring默認(rèn)scope是單例模式(scope="singleton"),這樣只會(huì)創(chuàng)建一個(gè)Action對(duì)象,每次訪問都是同一Action對(duì)象,數(shù)據(jù)不安全,struts2是要求每次次訪問都對(duì)應(yīng)不同的Action,scope="prototype"可以保證當(dāng)有請(qǐng)求的時(shí)候都創(chuàng)建一個(gè)Action對(duì)象。


        3、@Service


        @Service對(duì)應(yīng)的是業(yè)務(wù)層Bean,例如:


        @Service("userService")
        public?class?UserServiceImpl?implements?UserService?{
        ………
        }


        ?@Service("userService")注解是告訴Spring,當(dāng)Spring要?jiǎng)?chuàng)建UserServiceImpl的的實(shí)例時(shí),bean的名字必須叫做"userService",這樣當(dāng)Action需要使用UserServiceImpl的的實(shí)例時(shí),就可以由Spring創(chuàng)建好的"userService",然后注入給Action:在Action只需要聲明一個(gè)名字叫"userService"的變量來接收由Spring注入的"userService"即可,具體代碼如下:

        // 注入userService
        @Resource(name = "userService")
        private?UserService userService;


        注意:在Action聲明的"userService"變量的類型必須是"UserServiceImpl"或者是其父類"UserService",否則由于類型不一致而無法注入,由于Action中的聲明的"userService"變量使用了@Resource注解去標(biāo)注,并且指明了其name ?= ?"userService",這就等于告訴Spring,說我Action要實(shí)例化一個(gè)"userService",你Spring快點(diǎn)幫我實(shí)例化好,然后給我,當(dāng)Spring看到userService變量上的@Resource的注解時(shí),根據(jù)其指明的name屬性可以知道,Action中需要用到一個(gè)UserServiceImpl的實(shí)例,此時(shí)Spring就會(huì)把自己創(chuàng)建好的名字叫做"userService"的UserServiceImpl的實(shí)例注入給Action中的"userService"變量,幫助Action完成userService的實(shí)例化,這樣在Action中就不用通過"UserService ?userService = new ?UserServiceImpl();"這種最原始的方式去實(shí)例化userService了。如果沒有Spring,那么當(dāng)Action需要使用UserServiceImpl時(shí),必須通過"UserService ?userService = new ?UserServiceImpl();"主動(dòng)去創(chuàng)建實(shí)例對(duì)象,但使用了Spring之后,Action要使用UserServiceImpl時(shí),就不用主動(dòng)去創(chuàng)建UserServiceImpl的實(shí)例了,創(chuàng)建UserServiceImpl實(shí)例已經(jīng)交給Spring來做了,Spring把創(chuàng)建好的UserServiceImpl實(shí)例給Action,Action拿到就可以直接用了。Action由原來的主動(dòng)創(chuàng)建UserServiceImpl實(shí)例后就可以馬上使用,變成了被動(dòng)等待由Spring創(chuàng)建好UserServiceImpl實(shí)例之后再注入給Action,Action才能夠使用。這說明Action對(duì)"UserServiceImpl"類的“控制權(quán)”已經(jīng)被“反轉(zhuǎn)”了,原來主動(dòng)權(quán)在自己手上,自己要使用"UserServiceImpl"類的實(shí)例,自己主動(dòng)去new一個(gè)出來馬上就可以使用了,但現(xiàn)在自己不能主動(dòng)去new ?"UserServiceImpl"類的實(shí)例,new ?"UserServiceImpl"類的實(shí)例的權(quán)力已經(jīng)被Spring拿走了,只有Spring才能夠new ?"UserServiceImpl"類的實(shí)例,而Action只能等Spring創(chuàng)建好"UserServiceImpl"類的實(shí)例后,再“懇求”Spring把創(chuàng)建好的"UserServiceImpl"類的實(shí)例給他,這樣他才能夠使用"UserServiceImpl",這就是Spring核心思想“控制反轉(zhuǎn)”,也叫“依賴注入”,“依賴注入”也很好理解,Action需要使用UserServiceImpl干活,那么就是對(duì)UserServiceImpl產(chǎn)生了依賴,Spring把Acion需要依賴的UserServiceImpl注入(也就是“給”)給Action,這就是所謂的“依賴注入”。對(duì)Action而言,Action依賴什么東西,就請(qǐng)求Spring注入給他,對(duì)Spring而言,Action需要什么,Spring就主動(dòng)注入給他。


        4、@ Repository


        @Repository對(duì)應(yīng)數(shù)據(jù)訪問層Bean ,例如:


        @Repository(value="userDao")
        public?class?UserDaoImpl?extends?BaseDaoImpl<User> {
        ………
        }


        @Repository(value="userDao")注解是告訴Spring,讓Spring創(chuàng)建一個(gè)名字叫"userDao"的UserDaoImpl實(shí)例。


        當(dāng)Service需要使用Spring創(chuàng)建的名字叫"userDao"的UserDaoImpl實(shí)例時(shí),就可以使用@Resource(name = "userDao")注解告訴Spring,Spring把創(chuàng)建好的userDao注入給Service即可。


        // 注入userDao,從數(shù)據(jù)庫(kù)中根據(jù)用戶Id取出指定用戶時(shí)需要用到
        @Resource(name = "userDao")
        private?BaseDao userDao;


        Spring常用注解匯總


        本文匯總了Spring的常用注解,以方便大家查詢和使用,具體如下:


        使用注解之前要開啟自動(dòng)掃描功能,其中base-package為需要掃描的包(含子包)。

        @Configuration把一個(gè)類作為一個(gè)IoC容器,它的某個(gè)方法頭上如果注冊(cè)了@Bean,就會(huì)作為這個(gè)Spring容器中的Bean。
        @Scope注解 作用域
        @Lazy(true) 表示延遲初始化
        @Service用于標(biāo)注業(yè)務(wù)層組件、
        @Controller用于標(biāo)注控制層組件(如struts中的action)
        @Repository用于標(biāo)注數(shù)據(jù)訪問組件,即DAO組件。
        @Component泛指組件,當(dāng)組件不好歸類的時(shí)候,我們可以使用這個(gè)注解進(jìn)行標(biāo)注。
        @Scope用于指定scope作用域的(用在類上)
        @PostConstruct用于指定初始化方法(用在方法上)
        @PreDestory用于指定銷毀方法(用在方法上)
        @DependsOn:定義Bean初始化及銷毀時(shí)的順序
        @Primary:自動(dòng)裝配時(shí)當(dāng)出現(xiàn)多個(gè)Bean候選者時(shí),被注解為@Primary的Bean將作為首選者,否則將拋出異常
        @Autowired 默認(rèn)按類型裝配,如果我們想使用按名稱裝配,可以結(jié)合@Qualifier注解一起使用。如下:
        @Autowired @Qualifier("personDaoBean") 存在多個(gè)實(shí)例配合使用
        @Resource默認(rèn)按名稱裝配,當(dāng)找不到與名稱匹配的bean才會(huì)按類型裝配。
        @PostConstruct 初始化注解
        @PreDestroy 摧毀注解 默認(rèn) 單例? 啟動(dòng)就加載
        @Async異步方法調(diào)用


        原文鏈接:https://www.cnblogs.com/xiaoxi/p/5935009.html


        瀏覽 71
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            免费三级成人爱做片 | 操网址| 校花让我她我爽了好久动漫 | 孕妇毛茸茸孕妇孕交 | 女人 精A片一级户外 | 国产精品久久久久999 | 国产怕怕怕 | 黄色视频网站在线观看 | 欧美黄色一二三区 | 五月天无码免费视频 |