spring中使用注解代替xml配置
生活随笔
收集整理的這篇文章主要介紹了
spring中使用注解代替xml配置
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
今天兩部分內容,第一部分是注解,使用注解配置Spring,然后第二個是Spring中的AOP,今天就需要這兩部分,也沒有練習,第一個注解配置Spring,這三大框架都是用注解來配置,這三大框架,都是支持用注解配置的,那么三大框架的出現都是在JAVA1.5以前的,這樣1.5推出之后,只要有一個框架用了注解,這兩個框架不好意思不用,實際上這三個框架都支持使用注解了,但是Hibernate,還有咱們的Struts,咋沒說注解的事呢,那是因為,在企業開發當中,很少在hibernate和struts中用注解來開發,因為struts和hibernate用注解開發的話,導致咱們的類寫的亂七八糟的,而至于這個注解,使用最多的框架,那就是Spring,所以Spring這里面,是要講注解配置的,需要大家學習一下的,那第一個看下注解配置Spring,這個知識點也沒啥技術含量,看一下今天有哪些注解,代替昨天哪些配置文件就完事了,講起來還是比較簡單的,注解代替配置文件的,昨天寫的那些配置,都可以不用,然后用注解來代替,是這么點事,那咱們先做點準備工作,創建一個項目,spring_day02,然后準備工作第一導包,直接把這6個包加進來
第一步導包就完事了,第二步咱們準備對象,對象,咱們看有沒有現成的對象用,就用昨天現成的對象,昨天的對象很典型
package com.learn.bean;/*** @author Leon.Sun*/
public class User {public User() {System.out.println("User空參構造方法");}private String name;private Integer age;private Car car;public User(String name, Car car) {System.out.println("User(String name, Car car)");this.name = name;this.car = car;}public User(Car car, String name) {System.out.println("User(Car car, String name)");this.name = name;this.car = car;}public User(Integer name, Car car) {System.out.println("User(Integer name, Car car)");this.name = name + "";this.car = car;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public void init() {System.out.println("我是初始化方法!");}public void destory() {System.out.println("我是銷毀方法!");}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
package com.learn.bean;public class Car {private String name;private String color;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}@Overridepublic String toString() {return "Car [name=" + name + ", color=" + color + "]";}}
再把咱們的配置文件拿過來,接下來的話,注解配置開始講了,這里面沒什么道理,就是看怎么做就行了,第一步,需要為咱們的主配置文件,引入新的命名空間,或者叫做約束,昨天咱們導入的一個約束叫做beans,還記得嗎,那個xsd文件,你要是玩注解配置,包倒不要倒什么新包,但是你的這個配置文件呢,是需要再導入一個新的約束的,那這里導入一個新的約束的話,我們自己都做過了,首先你得preferences cata
然后在這里add
spring,schema,咱們今天用的這個命名空間,第一個要用的命名空間,是咱們的context
導法和昨天一模一樣,你把最后的名字復制,這里補個斜杠加上,然后在這里選擇Schema Location
然后引入到eclipse就完事了
再到咱們的Application這里面,右鍵xml edit,切換到design視圖
然后在beans上右鍵edit
Edit namespace,然后點擊add
因為他就一條道,然后再點Browse
選下面這個
找到剛才導入的context命名空間,往下找,這兒呢,是這個
是這個吧,然后呢,剩下的事情,把前面這一段粘到這里來,http://www.springframework.org/schema/context,然后這里面聽好,昨天的beans,Prefix前綴是空,但是在xml里面學過約束的知道,一個XML文檔當中,只允許有一個空的前綴,昨天學那個beans為空,那以后導入的命名空間絕對不能夠為空了,所以以后導入新命名空間,需要干這么一件事,把你剛才中間這一行,這一段的最后一個單詞,復制粘貼到這里來,這就是前綴,相比昨天導beans,區別就在于,前綴昨天是空,然后從昨天以后,今天開始,再導新的,都要把后面這個復制過來
新的命名空間就導入進來了,然后保存退出,這個時候看一下,第二步使用注解代替配置文件,相當于打開一個使用注解的開關,這個開關的話,因為咱們要用啊,這個時候你打<context:前綴,就有很多context約束下的元素,然后我們用到的是component-scan,這個component單詞知道是啥意思不,組件,scan就是掃描,翻譯過來就是自動掃描,咱們指定的組件,在Spring里面組件就是對象,理解為對象,咱們把對象放在Spring容器里管理,在Spring官方來說,把Component都放進來了,把組件放進來,所以理解成對象的掃描,后面這個是啥意思,base-package,基礎包,他的意思就是給他一個包名,從包下去掃描所有的類,掃這個包下的所有的類,看上面有沒有注解,咱們放到容器這兩個對象,都是在這個bean包下邊,所以你把bean包這個包名放到這,這是指定掃描這個包下的所有類中的注解,這里需要注意的是,在掃描包的時候,他不僅僅只掃描你給的這個包,如果這個包還有子包的話,也會掃描的,知道啥意思不,假設這個bean包下還有個haha包,這也會掃描,haha下邊還有個heihei包,也就是他在掃描的時候,他需要掃描子孫,所有包的,當然你這個learn這個包掃不掃,這個不掃,只掃你這個包的子包和子孫包,他之前的父包和爺包都不掃,這里面注意,在掃描時,掃描包時,會掃描指定包下的所有子孫包,當然很多人為了省事,比如全項目當中,所有項目都想用注解,他們就可能配置成這樣了,知道啥意思嗎,這樣就覆蓋了所有,我們還是講bean,這樣的話第一步就完事了,把這個截個圖放到這兒,這樣的話加個配置就可以了,然后接下來第三步,第三步就是在類中使用注解,完成配置
<?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 "><!-- 指定掃描com.learn.bean這個包下的所有類的注解 注意:掃描包時,會掃描指定包下的所有子孫包--><context:component-scan base-package="com.learn.bean"></context:component-scan></beans>
比如我們想把User對象配置到咱們的Spring容器當中,怎么做,這個構造我都給他刪掉,想把User對象配置到Spring容器當中的話,加上一個注解,@Component,這個叫組件,人家規定這個組件意思可明確了,那就是把User注冊到Spring容器中,這就是組件了,你也可以通過括號指定一個參數,這個參數的話用來指定對象放到Spring當中的這個名稱是什么,比如叫user,這個寫完以后,相當于在我們XML里面,怎么配置,<bean name="user">,然后class就是我們的User,你加這么一個注解,就相當于在這里面配置這個,咱們可以試一下,就加這一個注解,是不是好使,然后復制一個Demo過來,測試類過來
package com.learn.bean;import org.springframework.stereotype.Component;@Component("user")
// <bean name="user" class="com.learn.bean.User">
public class User {public User() {System.out.println("User空參構造方法");}private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public void init() {System.out.println("我是初始化方法!");}public void destory() {System.out.println("我是銷毀方法!");}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
a_annotation注解,在這創建容器,我把這個注釋打開就可以了,接下來你看,能不能獲得咱們注冊進來的User,不能,報錯了,報啥錯呢
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 創建方式1:空參構造*/@Testpublic void fun1() {/*** 1.創建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"對象*/User u = (User)ac.getBean("user");/*** 打印user對象*/
// System.out.println(u);}
}
咱們這個要玩注解的話,還得導一個包,他需要導入AOP包,老版本的不需要,spring-aop-4.2.4.RELEASE.jar,我們把這個步驟添加上,這個是新版本的
這個模塊在這里還要用到的,導完這個包之后,接下來再執行一下,是不是就獲取到這個對象了,這個時候就使用到了Component注解了,代替了咱們的bean語言,當然這里還有一個問題就是,Component這個注解,Spring在注冊bean的時候,一個早期注解,后來呢,又出現了這么幾個注解,@Service注解,user,還有@Controller,還有@Repository注解,后來又衍生出來這三個注解,啥意思呢,當年剛出現注解的時候,注冊bean只有一個注解,就是Component,后來使用者給Spring反饋,咱們注冊項目當中所有對象的時候,都用的同一個注解,這樣的話通過注解,很難區分對象是屬于哪一層,Spring聽了以后說,想一想,那咱們這樣解決吧,我再找出來三個注解,這三個注解和Component沒有任何區別,但是呢,這三注解,通過他的名字,你就能知道,你注冊的對象是屬于哪一層的對象,換句話講,對我們使用者來說,要想注冊一個Service層的對象,那你是不是可以使用這個注解,用于注冊Service層,那這個Controller,注冊什么層的呢,WEB層,為啥是WEB層,這個我們講MVC的時候,WEB就是servlet,或者咱們的action之類的,Repository其實是倉庫的意思,倉庫指的就是數據倉庫,數據庫,所以它是用來注冊DAO層的,所以我們要學如何把對象注冊到容器當中,一共有四種辦法,但是推薦使用能夠體現分成的三種,這個是具體注解,將對象注冊到容器中,就使用這三個注解,就這么簡單,然后接下來
package com.learn.bean;import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
public class User {private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}}
這四個用哪個都一樣,接下來第二個,咱們學會怎么注冊bean之后,比如這個User對象,怎么決定他的作用范圍,是單例的,還是prototype多例的,這個是可以使用@Scope屬性,你可以指定他的scopeName,如果是單例的話就是singleton,如果是原型就是prototype,單例因為是默認值,你改單例就不用加了,你要用的話肯定是改原型,那咱們來測一下
package com.learn.bean;import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")@Scope(scopeName="prototype")
public class User {private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}}
這個可以復制一份,u1,u2,是單例還是原型,打印一下u1==u2,那接下來咱們試一下,咱們改成原型,勢必導致是false
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 創建方式1:空參構造*/@Testpublic void fun1() {/*** 1.創建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"對象*/User u1 = (User)ac.getBean("user");User u2 = (User)ac.getBean("user");System.out.println(u1==u2);/*** 打印user對象*/
// System.out.println(u);}
}
比如我這個去掉,看他默認是不是單例的,執行一下,是不是true啊
package com.learn.bean;import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}}
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 創建方式1:空參構造*/@Testpublic void fun1() {/*** 1.創建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"對象*/User u1 = (User)ac.getBean("user");User u2 = (User)ac.getBean("user");System.out.println(u1==u2);/*** 打印user對象*/
// System.out.println(u);}
}
package com.learn.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {@Value("tom")private String name;private Integer age;private Car car;public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 創建方式1:空參構造*/@Testpublic void fun1() {/*** 1.創建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"對象*/User u1 = (User)ac.getBean("user");/*** 打印user對象*/System.out.println(u1);}
}
所以這里使用scope,指定對象的作用范圍,這是咱們學習的第二個知識點,修改對象的作用范圍,那下面咱們還要學習關于屬性的注入,比如說這個用戶,來給他一個名字,怎么做呢,很簡單,使用注解的話,是使用@Value的注解,Value就是值,括號,這里你要填寫一下,你要注入的值是什么,比如用戶咱們給他一個名字,tom,這是不是給name屬性賦值,賦值是tom,相當于什么玩意,相當于這里加一個property,這我就不去寫了,你們知道這是啥意思吧,就是把tom這個值注入到name屬性中,然后呢,直接執行一下,看控制臺打印,
User [name=tom, age=null, car=null]是不是有效果
但是跟你拓展一下,咱們這個使用value屬性,注入值的時候,有兩種選擇實際上,一種是把value屬性直接加載成員變量內部上,還有一種是把注解加載setName方法上,加在這里也是可以的
package com.learn.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {private String name;private Integer age;private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 創建方式1:空參構造*/@Testpublic void fun1() {/*** 1.創建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"對象*/User u1 = (User)ac.getBean("user");/*** 打印user對象*/System.out.println(u1);}
}
User [name=tom, age=null, car=null]
考慮一下,這兩種有什么區別,一種是加在成員變量上的,還有一種是加在set方法上,這其實挺矛盾的,說起來,為什么矛盾呢,你加在成員變量上,Spring在給這個對象賦值的時候,它是直接對field字段進行賦值,對field字符按進行賦值,學過反射嗎,知道Field是啥東西嗎,它是操作字段進行賦值的,而如果你放在setName上,他走的是set方法賦值的,通過反射的Field進行賦值,而下面是通過set方法賦值,這就是區別,當然對于我們賦值的結果來說,好像都一樣,但是從技術上來講,上面這種方式來賦值的話,破壞了咱們對象的封裝性,知道啥是破壞封裝性嗎,這是學面向對象最基礎的理論,面向對象三個特點,封裝,繼承和多態,啥叫封裝,怎么舉例子的,就是裝電腦,然后你把CPU,硬盤裝好之后,是不是要放到機箱里,放到機箱里的過程就叫做封裝,封裝的目的是啥啊,就是沒有必要直接去訪問到里面的CPU,那么你一摸就摸壞了,所以,把電腦的硬件都放在機箱里,什么音頻插口,USB插口,是不是這個意思,那咱們封裝類是不是也如此,封裝類的時候,把不希望外界看到的屬性私有,然后只暴露共有的對外的操作的方法,get和set,是這個意思嗎,那要是加在成員變量上,那是不是就直接訪問到內部的成員變量了,這是一個私有的,明白啥意思嗎,所以他是破壞了封裝性,破壞了封裝性就是面向對象,然后通過set方法賦值,它是推薦的,推薦使用,那毛病就毛病在這,在成員變量上加多清爽痛快,在方法上加是多別扭,所以咱們日常使用的時候,反正效果是一樣的,可能沒有人在意這個東西了,大家都喜歡加載屬性,成員變量上,這個仁者見仁智者見智,感覺是一個取舍問題呢,然后呢這就是value屬性,這塊的話給age也賦上一個值,括號給他來一個18歲,value等于18,注解學過吧,如果屬性只有一個,并且名字是value,就可以忽略屬性的鍵,記住這就是一個結論,如果注解中只有一個需要賦值,并且屬性名是value的話,那你是可以忽略屬性鍵的,所以凡是不寫鍵的,都是給什么屬性賦值,都是給value屬性賦值
package com.learn.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=null]
然后age賦完值以后執行一下,是不是沒問題
然后呢再往下,又該賦值了,只是賦值跟以前不太一樣了,以前是值,現在是對象,那這個的話看好,給對象賦值呢,這塊的話有點講究,你要是想把car屬性賦值過來,首先你要把Car注冊到容器當中,所以在Car上加上@Component,然后括號,在這里給他取一個名字,car,這樣的話car就放到容器當中了,接下來我要把car注入給user
package com.learn.bean;import org.springframework.stereotype.Component;@Component("car")
public class Car {private String name;private String color;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}@Overridepublic String toString() {return "Car [name=" + name + ", color=" + color + "]";}}
看我這怎么寫,有這么幾種方式,第一種方式,也就是最簡單的方式,只要加一個注解,@Autowired,這就完事了,只要加一個Autowired,Car就會被封裝進來,你看一下Car對象是不是有值了
package com.learn.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;@Autowiredprivate Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=Car [name=null, color=null]]
Car name昨天是蘭博基尼,今天來個什么,瑪莎拉蒂,然后color,來個嘔吐綠,再執行下你看看,是不是就進去了
package com.learn.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component("car")
public class Car {@Value("瑪莎拉蒂")private String name;@Value("嘔吐綠")private String color;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}@Overridepublic String toString() {return "Car [name=" + name + ", color=" + color + "]";}}
是不是就給了一個user,這就是第一種方式,叫Autowired,這個單詞,Auto是不是自動,wire是不是穿衣服的穿,翻譯一般翻譯成自動裝配,那有的人說好神奇,怎么自動裝配的,符合這個類型的對象,如果檢測到的話,找到這個對象,那你想,現在一看,這個Car類型,加了Autowired的,是不是會去容器中找Car類型的對象,那是不是能找著,找著了一個Car,是不是就給他了,知道啥意思不,那這種寫法,爽是爽,但是對象一多的時候會有這個問題,你們猜到了,啥問題,這種自動裝配的方式,假設我要把這個Car,注冊了好幾輛在容器當中呢,聽懂啥意思不,比如我有三輛車,在容器當中,那怎么能做到呢,你在這里放一個傳統的bean,來一個name,再來一個什么,class,這也是咱們的Car,然后這一塊叫做car2,咱們這一塊再來一個屬性,比如property,name等于name,value是布加迪威龍,那這樣的話再看,現在我Spring容器當中,是不是兩輛車
<?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 "><!-- 指定掃描com.learn.bean這個包下的所有類的注解 注意:掃描包時,會掃描指定包下的所有子孫包--><context:component-scan base-package="com.learn.bean"></context:component-scan><bean name="car2" class="com.learn.bean.Car"><property name="name" value="布加迪威龍"></property><property name="color" value="black"></property></bean></beans>
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 創建方式1:空參構造*/@Testpublic void fun1() {/*** 1.創建容器*/ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"對象*/User u1 = (User)ac.getBean("user");/*** 打印user對象*/System.out.println(u1);}
}
那我這個自動裝配的話,它是按照類型會去容器中匹配,那這樣的話,你給他這么一裝他就迷茫了,哪輛呢,你看瑪莎拉蒂User [name=tom, age=18, car=Car [name=瑪莎拉蒂, color=嘔吐綠]]
第一種方式有個問題,就是如果有多個類型的話,他自動裝配的話,自動裝配的話又有一個問題,如果匹配到多給類型一致的對象,將無法選擇具體注入哪一個對象,這樣的話怎么辦呢,咱們給Autowired加一個輔助注解,@Qualifer,然后這個注解,填入一個你要注入的名字,就像布加迪威龍,剛才咱們注冊的叫car2,那你就在這寫上,car2,知道啥意思,這樣的話等于說自動裝配,告訴他找名為car2的車
package com.learn.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;/*** 自動裝配* 問題:如果匹配多個類型一致的對象,講無法選擇具體注入哪一個對象*/@Autowired@Qualifier("car2")private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=Car [name=布加迪威龍, color=black]]
看到效果了嗎,這樣的話怎么找都是布加迪威龍,這樣的話他就是第二種方式,使用Qualifier,使用@Qualifier注解,告訴咱們的Spring容器,自動裝配哪個名稱的對象,這里成對配套使用,然后最后再介紹一種方式,這兩個先注掉,其實如果你是對象類型,有多個的話,其實并不建議你用這兩個注解一塊用,這樣用太羅嗦了,有一個注解他不是自動裝配,直接指名道姓的,叫做Resource屬性,指名道姓的告訴他要裝配哪一個,car2,這樣的話一個注解,是不是就搞定了,他不是自動注解,他完全是手動注解,手動注入,指定注入哪個名稱的對象,這樣的話是不是還是注入布加迪威龍,執行一下你看看,是不是這個效果
package com.learn.bean;import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;/*** 自動裝配* 問題:如果匹配多個類型一致的對象,講無法選擇具體注入哪一個對象*/
// @Autowired
// @Qualifier("car2")/*** 手動注入,指定注入哪個名稱的對象*/@Resource(name="car2")private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=Car [name=布加迪威龍, color=black]]
你要想輸出瑪莎拉蒂,再執行一下
package com.learn.bean;import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;/*** 自動裝配* 問題:如果匹配多個類型一致的對象,講無法選擇具體注入哪一個對象*/
// @Autowired
// @Qualifier("car2")/*** 手動注入,指定注入哪個名稱的對象*/@Resource(name="car")private Car car;public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
User [name=tom, age=18, car=Car [name=瑪莎拉蒂, color=嘔吐綠]]
是不是這個效果,這就是第三種注入對象的方式了,然后呢其中,推薦的話我其實推薦這種,這就是三種對象類型的注入方式,然后咱們以后最好的方式,就是指名道姓,直接指定注入哪一個,這是類型注入,接下來還沒有完,最后有兩個注解,比如說這個User,咱們指定一個初始化方法,銷毀方法,咱們配置文件不是學了,pubilc void init方法,這個就打印一下,這是初始化方法,比如這個init方法我想讓他作為初始化方法,可以在他這個方法上加上一個@PostConstruct,這個單詞翻譯過來,post是在什么之后,Construct是不是構造,所以翻譯過來是什么,構造之后調用,在對象被構造后,或者是被創建吧,創建后調用,相當于咱們以前學過的什么東西,init-method,然后這個destory方法,叫做@PreDestroy,PreDestroy,Pre是在什么之前,Destory是銷毀,在對象銷毀之前,調用的,相當于destroy-method,知道啥意思不
package com.learn.bean;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;//@Component("user")
// <bean name="user" class="com.learn.bean.User">
// @Service("user")
// @Controller("user")@Repository("user")
// @Scope(scopeName="prototype")
public class User {private String name;@Value(value="18")private Integer age;/*** 自動裝配* 問題:如果匹配多個類型一致的對象,講無法選擇具體注入哪一個對象*/
// @Autowired
// @Qualifier("car2")/*** 手動注入,指定注入哪個名稱的對象*/@Resource(name="car")private Car car;/*** 在對象被創建后調用.init-method*/@PostConstructpublic void init() {System.out.println("初始化方法!");}/*** 在銷毀之前調用 destroy-method*/@PreDestroypublic void destory() {System.out.println("銷毀方法!");}public String getName() {return name;}@Value("tom")public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "User [name=" + name + ", age=" + age + ", car=" + car + "]";}}
那接下來咱們再試一下看看,這里面咱們的銷毀方法,你要想看到打印的話,你要調用它的close方法,那這個close方法要調的話,引用得用子類,然后最后來一個ac.close,這回你再執行你看看,看到這個效果了
package com.learn.a_annotation;import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;import com.learn.bean.User;public class Demo {/*** 創建方式1:空參構造*/@Testpublic void fun1() {/*** 1.創建容器*/ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");/*** 2.向容器要"user"對象*/User u1 = (User)ac.getBean("user");/*** 打印user對象*/System.out.println(u1);ac.close();}
}
初始化方法!
User [name=tom, age=18, car=Car [name=瑪莎拉蒂, color=嘔吐綠]]
銷毀方法!
作用域改成singleton,為啥呢,每次都創建一個新的,每次新的給你就不管了,只有放在容器中的才會納入完整性里面,看到了效果了,這樣的話這就是咱們的初始化和銷毀,初始化銷毀,初始化以及銷毀方法,這樣的話咱們注解就到這,這是Spring當中的注解,代替配置文件
?
總結
以上是生活随笔為你收集整理的spring中使用注解代替xml配置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring配置详解-复杂类型注入
- 下一篇: spring整合junit测试