SSM學習之Spring

SSM-Spring框架學習

一耕突、概念

Spring是一個輕量級的控制反轉(IoC)和面向切面(AOP)的容器(框架)。

二、優(yōu)點

1巩剖、Spring是一個開源免費的框架 , 容器 .

2适滓、Spring是一個輕量級的框架 , 非侵入式的 .

3敦迄、控制反轉 IoC , 面向切面 Aop

4、對事物的支持 , 對框架的支持

三凭迹、組成

3.1 Spring 框架是一個分層架構

由 7 個定義良好的模塊組成罚屋,Spring 模塊構建在核心容器之上,核心容器定義了創(chuàng)建嗅绸、配置和管理 bean 的方式 .

圖片

3.2 組成 Spring 框架的每個模塊(或組件)都可以單獨存在:

  • 核心容器:核心容器提供 Spring 框架的基本功能脾猛。核心容器的主要組件是 BeanFactory,它是工廠模式的實現鱼鸠。BeanFactory 使用控制反轉(IOC) 模式將應用程序的配置和依賴性規(guī)范與實際的應用程序代碼分開猛拴。

  • Spring 上下文:Spring 上下文是一個配置文件羹铅,向 Spring 框架提供上下文信息。Spring 上下文包括企業(yè)服務愉昆,例如 JNDI职员、EJB、電子郵件跛溉、國際化焊切、校驗和調度功能。

  • Spring AOP:通過配置管理特性芳室,Spring AOP 模塊直接將面向切面的編程功能 , 集成到了 Spring 框架中蛛蒙。所以,可以很容易地使 Spring 框架管理任何支持 AOP的對象渤愁。Spring AOP 模塊為基于 Spring 的應用程序中的對象提供了事務管理服務牵祟。通過使用 Spring AOP,不用依賴組件抖格,就可以將聲明性事務管理集成到應用程序中诺苹。

  • Spring DAO:JDBC DAO 抽象層提供了有意義的異常層次結構,可用該結構來管理異常處理和不同數據庫供應商拋出的錯誤消息雹拄。異常層次結構簡化了錯誤處理收奔,并且極大地降低了需要編寫的異常代碼數量(例如打開和關閉連接)。Spring DAO 的面向 JDBC 的異常遵從通用的 DAO 異常層次結構滓玖。

  • Spring ORM:Spring 框架插入了若干個 ORM 框架坪哄,從而提供了 ORM 的對象關系工具,其中包括 JDO势篡、Hibernate 和 iBatis SQL Map翩肌。所有這些都遵從 Spring 的通用事務和 DAO 異常層次結構。

  • Spring Web 模塊:Web 上下文模塊建立在應用程序上下文模塊之上禁悠,為基于 Web 的應用程序提供了上下文念祭。所以,Spring 框架支持與 Jakarta Struts 的集成碍侦。Web 模塊還簡化了處理多部分請求以及將請求參數綁定到域對象的工作粱坤。

  • Spring MVC 框架:MVC 框架是一個全功能的構建 Web 應用程序的 MVC 實現。通過策略接口瓷产,MVC 框架變成為高度可配置的站玄,MVC 容納了大量視圖技術,其中包括 JSP濒旦、Velocity株旷、Tiles、iText 和 POI疤估。

圖片

拓展

Spring Boot與Spring Cloud

  • Spring Boot 是 Spring 的一套快速配置腳手架灾常,可以基于Spring Boot 快速開發(fā)單個微服務;

  • Spring Cloud是基于Spring Boot實現的;

  • Spring Boot專注于快速铃拇、方便集成的單個微服務個體钞瀑,Spring Cloud關注全局的服務治理框架;

  • Spring Boot使用了約束優(yōu)于配置的理念慷荔,很多集成方案已經幫你選擇好了雕什,能不配置就不配置 , Spring Cloud很大的一部分是基于Spring Boot來實現,Spring Boot可以離開Spring Cloud獨立使用開發(fā)項目显晶,但是Spring Cloud離不開Spring Boot贷岸,屬于依賴的關系。

  • SpringBoot在SpringClound中起到了承上啟下的作用磷雇,如果你要學習SpringCloud必須要學習SpringBoot偿警。

四、控制反轉(IOC)

4.1 本質

  • 控制反轉IoC(Inversion of Control)唯笙,是一種設計思想螟蒸,DI(依賴注入)是實現IoC的一種方法

  • 控制反轉是一種通過描述(XML或注解)并通過第三方去生產或獲取特定對象的方式。在Spring中實現控制反轉的是IoC容器崩掘,其實現方法是依賴注入(Dependency Injection,DI)

  • IoC是Spring框架的核心內容

    Spring容器在初始化時先讀取配置文件七嫌,根據配置文件或元數據創(chuàng)建與組織對象存入容器中,程序使用時再從Ioc容器中取出需要的對象苞慢。<在配置文件加載的時候诵原,容器中管理的對象就已經初始化了>

    圖片

采用XML方式配置Bean的時候,Bean的定義信息是和實現分離的挽放,而采用注解的方式可以把兩者合為一體绍赛,Bean的定義信息直接以注解的形式定義在實現類中,從而達到了零配置的目的辑畦。

五惹资、快速上手Spring

5.1 配置環(huán)境

導入Jar包

注 : spring 需要導入commons-logging進行日志記錄 . 我們利用maven , 他會自動下載對應的依賴項 (包含測試依賴).

<dependencies>
 <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-webmvc</artifactId>
 <version>5.2.0.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.12</version>
 <scope>test</scope>
 </dependency>
</dependencies></pre>

5.2 編寫代碼

1、編寫一個Hello實體類

public class Hello {
 private String name;

 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }

 public void show(){
 System.out.println("Hello,"+ name );
 }
}

2航闺、編寫我們的spring文件 , 這里我們命名為beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">
 <!--bean就是java對象 , 由Spring創(chuàng)建和管理-->
 <bean id="hello" class="com.kuang.pojo.Hello">
 <property name="name" value="Spring"/>
 </bean>
</beans></pre>

3褪测、我們可以去進行測試了 .

@Test
public void test(){
 //解析beans.xml文件 , 生成管理相應的Bean對象
 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 //getBean : 參數即為spring配置文件中bean的id .
 Hello hello = (Hello) context.getBean("hello");
 hello.show();
}

思考

  • Hello 對象是誰創(chuàng)建的 ? 【hello 對象是由Spring創(chuàng)建的

  • Hello 對象的屬性是怎么設置的 ? hello 對象的屬性是由Spring容器設置的

這個過程就叫控制反轉 :

  • 控制 : 誰來控制對象的創(chuàng)建 , 傳統(tǒng)應用程序的對象是由程序本身控制創(chuàng)建的 , 使用Spring后 , 對象是由Spring來創(chuàng)建的

  • 反轉 : 程序本身不創(chuàng)建對象 , 而變成被動的接收對象 .

依賴注入 : 就是利用set方法來進行注入的.

IOC是一種編程思想,由主動的編程變成被動的接收

可以通過newClassPathXmlApplicationContext去瀏覽一下底層源碼 .

5.3 IOC創(chuàng)建對象方式

5.3.1 通過無參構造方法來創(chuàng)建

1潦刃、User.java

public class User {

 private String name;

 public User() {
 System.out.println("user無參構造方法");
 }

 public void setName(String name) {
 this.name = name;
 }

 public void show(){
 System.out.println("name="+ name );
 }

}

2侮措、beans.xml

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

 <bean id="user" class="com.kuang.pojo.User">
 <property name="name" value="kuangshen"/>
 </bean>

</beans>

3、測試類

@Test
public void test(){
 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 //在執(zhí)行getBean的時候, user已經創(chuàng)建好了 , 通過無參構造
 User user = (User) context.getBean("user");
 //調用對象的方法 .
 user.show();
}

結果可以發(fā)現乖杠,在調用show方法之前分扎,User對象已經通過無參構造初始化了!

5.3.2 通過有參構造方法來創(chuàng)建

1胧洒、UserT . java

public class UserT {

 private String name;

 public UserT(String name) {
 this.name = name;
 }

 public void setName(String name) {
 this.name = name;
 }

 public void show(){
 System.out.println("name="+ name );
 }

}

2畏吓、beans.xml 有三種方式編寫

<!-- 第一種根據index參數下標設置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <!-- index指構造方法 , 下標從0開始 -->
   <constructor-arg index="0" value="kuangshen2"/>
</bean>
<!-- 第二種根據參數名字設置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <!-- name指參數名 -->
   <constructor-arg name="name" value="kuangshen2"/>
</bean>
<!-- 第三種根據參數類型設置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>

3墨状、測試

@Test
public void testT(){
 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 UserT user = (UserT) context.getBean("userT");
 user.show();
}

結論:在配置文件加載的時候。其中管理的對象都已經初始化了菲饼!

六肾砂、Spring配置

6.1 別名

alias 設置別名 , 為bean設置別名 , 可以設置多個別名

<!--設置別名:在獲取Bean的時候可以使用別名獲取-->
<alias name="userT" alias="userNew"/>

6.2 Bean的配置

<!--bean就是java對象,由Spring創(chuàng)建和管理-->

<!--
 id 是bean的標識符,要唯一,如果沒有配置id,name就是默認標識符
 如果配置id,又配置了name,那么name是別名
 name可以設置多個別名,可以用逗號,分號,空格隔開
 如果不配置id和name,可以根據applicationContext.getBean(.class)獲取對象;

class是bean的全限定名=包名+類名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
 <property name="name" value="Spring"/>
</bean>

6.3 import

團隊的合作通過import來實現 .

七、依賴注入(DI)

7.1 概念

  • 依賴注入(Dependency Injection,DI)宏悦。

  • 依賴 : 指Bean對象的創(chuàng)建依賴于容器 . Bean對象的依賴資源 .

  • 注入 : 指Bean對象所依賴的資源 , 由容器來設置和裝配 .

7.2 Set注入

要求被注入的屬性 , 必須有set方法 , set方法的方法名由set + 屬性首字母大寫 , 如果屬性是boolean類型 , 沒有set方法 , 是 is .

測試pojo類 :

Address.java

 public class Address {

     private String address;

     public String getAddress() {
         return address;
    }

     public void setAddress(String address) {
         this.address = address;
    }
 }

Student.java

package com.kuang.pojo;

 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;

 public class Student {

     private String name;
     private Address address;
     private String[] books;
     private List<String> hobbys;
     private Map<String,String> card;
     private Set<String> games;
     private String wife;
     private Properties info;

     public void setName(String name) {
         this.name = name;
    }

     public void setAddress(Address address) {
         this.address = address;
    }

     public void setBooks(String[] books) {
         this.books = books;
    }

     public void setHobbys(List<String> hobbys) {
         this.hobbys = hobbys;
    }

     public void setCard(Map<String, String> card) {
         this.card = card;
    }

     public void setGames(Set<String> games) {
         this.games = games;
    }

     public void setWife(String wife) {
         this.wife = wife;
    }

     public void setInfo(Properties info) {
         this.info = info;
    }

     public void show(){
         System.out.println("name="+ name
                 + ",address="+ address.getAddress()
                 + ",books="
        );
         for (String book:books){
             System.out.print("<<"+book+">>\t");
        }
         System.out.println("\n愛好:"+hobbys);

         System.out.println("card:"+card);

         System.out.println("games:"+games);

         System.out.println("wife:"+wife);

         System.out.println("info:"+info);

    }
 }

7.2.1 常量注入

<bean id="student" class="com.kuang.pojo.Student">
     <property name="name" value="小明"/>
 </bean></pre>

測試:

@Test
 public void test01(){
     ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

     Student student = (Student) context.getBean("student");

     System.out.println(student.getName());

 }

7.2.2 Bean注入

注意點:這里的值是一個引用镐确,ref

<bean id="addr" class="com.kuang.pojo.Address">
     <property name="address" value="重慶"/>
 </bean>

 <bean id="student" class="com.kuang.pojo.Student">
     <property name="name" value="小明"/>
     <property name="address" ref="addr"/>
 </bean>

7.2.3 數組注入

 <bean id="student" class="com.kuang.pojo.Student">
     <property name="name" value="小明"/>
     <property name="address" ref="addr"/>
     <property name="books">
         <array>
             <value>西游記</value>
             <value>紅樓夢</value>
             <value>水滸傳</value>
         </array>
     </property>
 </bean>

7.2.4 List注入

 <property name="hobbys">
 <list>
 <value>聽歌</value>
 <value>看電影</value>
 <value>爬山</value>
 </list>
 </property>

7.2.5 Map注入

<property name="card">
 <map>
 <entry key="中國郵政" value="456456456465456"/>
 <entry key="建設" value="1456682255511"/>
 </map>
 </property>

7.2.6 set注入

 <property name="games">
 <set>
 <value>LOL</value>
 <value>BOB</value>
 <value>COC</value>
 </set>
 </property>

7.2.7 Null注入

<property name="wife"><null/></property>

7.2.8 Properties注入

<property name="info">
 <props>
 <prop key="學號">20190604</prop>
 <prop key="性別">男</prop>
 <prop key="姓名">小明</prop>
 </props>
 </property>

擴展:Properties和Map都是以鍵值對的形式存儲的,但是他們有什么區(qū)別嗎饼煞?

最大的區(qū)別就是 Properties可以直接導入IO流 讀取IO流中的數據 并且能把自己的元素輸出到IO流中源葫。就是我們可以去寫properties文件,進行讀寫砖瞧。

7.3 p命名和c命名注入

7.3.1 P命名空間注入 : 需要在頭文件中加入約束文件

導入約束 : xmlns:p="http://www.springframework.org/schema/p"

 <!--P(屬性: properties)命名空間 , 屬性依然要設置set方法-->
 <bean id="user" class="com.kuang.pojo.User" p:name="狂神" p:age="18"/>

7.3.2 c 命名空間注入 : 需要在頭文件中加入約束文件

導入約束 : xmlns:c="http://www.springframework.org/schema/c"
 <!--C(構造: Constructor)命名空間 , 屬性依然要設置set方法-->
 <bean id="user" class="com.kuang.pojo.User" c:name="狂神" c:age="18"/>

7.4 Bean的作用域

在Spring中息堂,那些組成應用程序的主體及由Spring IoC容器所管理的對象,被稱之為bean块促。簡單地講储矩,bean就是由IoC容器初始化、裝配及管理的對象 .

圖片

7.4.1 Singleton

當一個bean的作用域為Singleton褂乍,那么Spring IoC容器中只會存在一個共享的bean實例持隧,并且所有對bean的請求,只要id與該bean定義相匹配逃片,則只會返回bean的同一實例屡拨。

<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton"

7.4.2 Prototype

當一個bean的作用域為Prototype,表示一個bean定義對應多個對象實例褥实。Prototype作用域的bean會導致在每次對該bean請求(將其注入到另一個bean中呀狼,或者以程序的方式調用容器的getBean()方法)時都會創(chuàng)建一個新的bean實例。Prototype是原型類型损离,它在我們創(chuàng)建容器的時候并沒有實例化哥艇,而是當我們獲取bean的時候才會去創(chuàng)建一個對象,而且我們每次獲取到的對象都不是同一個對象僻澎。

<bean id="account" class="com.foo.DefaultAccount" scope="prototype"/>
 或者
 <bean id="account" class="com.foo.DefaultAccount" singleton="false"/>

對有狀態(tài)的bean應該使用prototype作用域貌踏,而對無狀態(tài)的bean則應該使用singleton作用域

補充:scope中單例(singleton)和prototype的優(yōu)缺點:

singleton(默認):優(yōu)點:不會new對象,節(jié)省資源窟勃;缺點:在處理高并發(fā)的時候可能會延遲或數據不一致 prototype:優(yōu)點:多線程穩(wěn)定 缺點:每次在創(chuàng)建浪費資源 多線程使用prototype祖乳,單線程使用singleton

7.4.3 Request

當一個bean的作用域為Request,表示在一次HTTP請求中秉氧,一個bean定義對應一個實例眷昆。即每個HTTP請求都會有各自的bean實例,它們依據某個bean定義創(chuàng)建而成。

針對每次HTTP請求亚斋,Spring容器會根據loginAction bean的定義創(chuàng)建一個全新的LoginAction bean實例作媚,且該loginAction bean實例僅在當前HTTP request內有效。當處理請求結束帅刊,request作用域的bean實例將被銷毀纸泡。

<bean id="loginAction" class=cn.csdn.LoginAction" scope="request"/>

7.4.3 Session

當一個bean的作用域為Session,表示在一個HTTP Session中厚掷,一個bean定義對應一個實例弟灼。該作用域僅在基于web的Spring ApplicationContext情形下有效级解。

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

針對某個HTTP Session冒黑,Spring容器會根據userPreferences bean定義創(chuàng)建一個全新的userPreferences bean實例,且該userPreferences bean僅在當前HTTP Session內有效.

八勤哗、自動裝配

8.1 概念

  • 自動裝配是使用spring滿足bean依賴的一種方法

  • spring會在應用上下文中為某個bean尋找其依賴的bean抡爹。

8.2 裝配機制

Spring中bean有三種裝配機制,分別是:

  1. 在xml中顯式配置芒划;

  2. 在java中顯式配置冬竟;

  3. 隱式的bean發(fā)現機制和自動裝配。

8.3 實現

Spring的自動裝配需要從兩個角度來實現民逼,或者說是兩個操作:

  1. 組件掃描(component scanning):spring會自動發(fā)現應用上下文中所創(chuàng)建的bean泵殴;

  2. 自動裝配(autowiring):spring自動滿足bean之間的依賴,也就是我們說的IoC/DI拼苍;

1笑诅、新建一個項目

2、新建兩個實體類疮鲫,Cat Dog 都有一個叫的方法

public class Cat {
 public void shout() {
 System.out.println("miao~");
 }
}
public class Dog {
 public void shout() {
 System.out.println("wang~");
 }
}

3吆你、新建一個用戶類 User

public class User {
 private Cat cat;
 private Dog dog;
 private String str;
}

4、編寫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"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
 http://www.springframework.org/schema/beans/spring-beans.xsd">

 <bean id="dog" class="com.kuang.pojo.Dog"/>
 <bean id="cat" class="com.kuang.pojo.Cat"/>

 <bean id="user" class="com.kuang.pojo.User">
 <property name="cat" ref="cat"/>
 <property name="dog" ref="dog"/>
 <property name="str" value="qinjiang"/>
 </bean>
</beans>

5俊犯、測試

public class MyTest {
 @Test
 public void testMethodAutowire() {
 ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
 User user = (User) context.getBean("user");
 user.getCat().shout();
 user.getDog().shout();
 }
}

8.3.1 autowire byName (按名稱自動裝配)

由于在手動配置xml過程中妇多,常常發(fā)生字母缺漏和大小寫等錯誤,而無法對其進行檢查燕侠,使得開發(fā)效率降低者祖。

采用自動裝配將避免這些錯誤,并且使配置簡單化绢彤。

測試:

1咸包、修改bean配置,增加一個屬性 autowire="byName"

<bean id="user" class="com.kuang.pojo.User" autowire="byName">
 <property name="str" value="qinjiang"/>
</bean>

2杖虾、再次測試烂瘫,結果依舊成功輸出!

3、我們將 cat 的bean id修改為 catXXX

4坟比、再次測試芦鳍, 執(zhí)行時報空指針java.lang.NullPointerException。因為按byName規(guī)則找不對應set方法葛账,真正的setCat就沒執(zhí)行柠衅,對象就沒有初始化,所以調用時就會報空指針錯誤籍琳。

小結:

當一個bean節(jié)點帶有 autowire byName的屬性時菲宴。

  1. 將查找其類中所有的set方法名,例如setCat趋急,獲得將set去掉并且首字母小寫的字符串喝峦,即cat。

  2. 去spring容器中尋找是否有此字符串名稱id的對象呜达。

  3. 如果有谣蠢,就取出注入;如果沒有查近,就報空指針異常眉踱。

8.3.2 autowire byType (按類型自動裝配)

使用autowire byType首先需要保證:同一類型的對象,在spring容器中唯一霜威。如果不唯一谈喳,會報不唯一的異常。NoUniqueBeanDefinitionException

測試:

1戈泼、將user的bean配置修改一下 : autowire="byType"

2婿禽、測試,正常輸出

3矮冬、在注冊一個cat 的bean對象谈宛!

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>

<bean id="user" class="com.kuang.pojo.User" autowire="byType">
 <property name="str" value="qinjiang"/>
</bean>

4、測試胎署,報錯:NoUniqueBeanDefinitionException

5吆录、刪掉cat2,將cat的bean名稱改掉琼牧!測試恢筝!因為是按類型裝配,所以并不會報異常巨坊,也不影響最后的結果撬槽。甚至將id屬性去掉,也不影響結果趾撵。

九侄柔、使用注解

9.1 配置

jdk1.5開始支持注解共啃,spring2.5開始全面支持注解。

準備工作:利用注解的方式注入屬性暂题。

1移剪、在spring配置文件中引入context文件頭

xmlns:context="http://www.springframework.org/schema/context"

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd

2、開啟屬性注解支持薪者!

<context:annotation-config/>

9.2 @Autowired

  • @Autowired是按類型自動轉配的纵苛,不支持id匹配。

  • 需要導入 spring-aop的包言津!

測試:

1攻人、將User類中的set方法去掉,使用@Autowired注解

public class User {
   @Autowired
   private Cat cat;
   @Autowired
   private Dog dog;
   private String str;

   public Cat getCat() {
       return cat;
  }
   public Dog getDog() {
       return dog;
  }
   public String getStr() {
       return str;
  }
}

2悬槽、此時配置文件內容

<context:annotation-config/>

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="user" class="com.kuang.pojo.User"/>

3怀吻、測試,成功輸出結果陷谱!

【補充】

@Autowired(required=false) 說明:false烙博,對象可以為null瑟蜈;true烟逊,對象必須存對象,不能為null铺根。

//如果允許對象為null宪躯,設置required = false,默認為true
@Autowired(required = false)
private Cat cat;

9.3 @Qualifier

  • @Autowired是根據類型自動裝配的,加上@Qualifier則可以根據byName的方式自動裝配

  • @Qualifier不能單獨使用位迂。

測試實驗步驟:

1访雪、配置文件修改內容,保證類型存在對象掂林。且名字不為類的默認名字臣缀!

<bean id="dog1" class="com.kuang.pojo.Dog"/>
<bean id="dog2" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>

2、沒有加Qualifier測試泻帮,直接報錯

3精置、在屬性上添加Qualifier注解

@Autowired
@Qualifier(value = "cat2")
private Cat cat;
@Autowired
@Qualifier(value = "dog2")
private Dog dog;

測試婆誓,成功輸出掐禁!

9.4 @Resource

  • @Resource如有指定的name屬性,先按該屬性進行byName方式查找裝配冯痢;

  • 其次再進行默認的byName方式進行裝配元莫;

  • 如果以上都不成功赖阻,則按byType的方式自動裝配。

  • 都不成功踱蠢,則報異常火欧。

實體類:

public class User {
   //如果允許對象為null,設置required = false,默認為true
   @Resource(name = "cat2")
   private Cat cat;
   @Resource
   private Dog dog;
   private String str;
}

beans.xml

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>
<bean id="cat2" class="com.kuang.pojo.Cat"/>

<bean id="user" class="com.kuang.pojo.User"/>

測試:結果OK

配置文件2:beans.xml , 刪掉cat2

<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="cat1" class="com.kuang.pojo.Cat"/>

實體類上只保留注解

@Resource
private Cat cat;
@Resource
private Dog dog;

結果:OK

結論:先進行byName查找苇侵,失斃胩铡;再進行byType查找衅檀,成功招刨。

9.5 @Nullable <補充>

字段標記了這個注解,說明這個字段可以為null

小結

@Autowired與@Resource異同:

1哀军、@Autowired與@Resource都可以用來裝配bean沉眶。都可以寫在字段上,或寫在setter方法上杉适。

2谎倔、@Autowired默認按類型裝配(屬于spring規(guī)范),默認情況下必須要求依賴對象必須存在猿推,如果要允許null 值片习,可以設置它的required屬性為false,如:@Autowired(required=false) 蹬叭,如果我們想使用名稱裝配可以結合@Qualifier注解進行使用

3藕咏、@Resource(屬于J2EE復返),默認按照名稱進行裝配秽五,名稱可以通過name屬性進行指定孽查。如果沒有指定name屬性,當注解寫在字段上時坦喘,默認取字段名進行按照名稱查找盲再,如果注解寫在setter方法上默認取屬性名進行裝配。當找不到與名稱匹配的bean時才按照類型進行裝配瓣铣。但是需要注意的是答朋,如果name屬性一旦指定,就只會按照名稱進行裝配棠笑。

它們的作用相同都是用注解方式注入對象梦碗,但執(zhí)行順序不同。@Autowired先byType腐晾,@Resource先byName叉弦。

十、使用注解開發(fā)

10.1 配置

在spring4之后藻糖,想要使用注解形式淹冰,必須得要引入aop的包

圖片

在配置文件當中,還得要引入一個context約束

<?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:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">
</beans>

10.2 bean的實現

1巨柒、配置掃描哪些包下的注解

<!--指定注解掃描包-->
<context:component-scan base-package="com.kuang.pojo"/>

2樱拴、在指定包下編寫類柠衍,增加注解

@Component("user")
// 相當于配置文件中 <bean id="user" class="當前注解的類"/>
public class User {
   public String name = "alen";
}

3、測試

@Test
public void test(){
   ApplicationContext applicationContext =
       new ClassPathXmlApplicationContext("beans.xml");
   User user = (User) applicationContext.getBean("user");
   System.out.println(user.name);
}

10.3 屬性注入

使用注解注入屬性

1晶乔、可以不用提供set方法珍坊,直接在直接名上添加@value("值")

@Component("user")
// 相當于配置文件中 <bean id="user" class="當前注解的類"/>
public class User {
   @Value("alen")
   // 相當于配置文件中 <property name="name" value="alen"/>
   public String name;
}

2、如果提供了set方法正罢,在set方法上添加@value("值");

@Component("user")
public class User {

   public String name;

   @Value("alen")
   public void setName(String name) {
       this.name = name;
  }
}

10.4 衍生注解

@Component三個衍生注解

為了更好的進行分層阵漏,Spring可以使用其它三個注解,功能一樣翻具,目前使用哪一個功能都一樣履怯。

  • @Controller:web層

  • @Service:service層

  • @Repository:dao層

寫上這些注解,就相當于將這個類交給Spring管理裝配了裆泳!

10.5 作用域

@scope

  • singleton:默認的叹洲,Spring會采用單例模式創(chuàng)建這個對象。關閉工廠 工禾,所有的對象都會銷毀运提。

  • prototype:多例模式。關閉工廠 闻葵,所有的對象不會銷毀民泵。內部的垃圾回收機制會回收

@Controller("user")
@Scope("prototype")
public class User {
   @Value("alen")
   public String name;
}

小結:

XML與注解比較

  • XML可以適用任何場景 ,結構清晰笙隙,維護方便

  • 注解不是自己提供的類使用不了洪灯,開發(fā)簡單方便

xml與注解整合開發(fā) :推薦最佳實踐

  • xml管理Bean

  • 注解完成屬性注入

  • 使用過程中坎缭, 可以不用掃描竟痰,掃描是為了類上的注解

<context:annotation-config/>

作用:

  • 進行注解驅動注冊,從而使注解生效

  • 用于激活那些已經在spring容器里注冊過的bean上面的注解掏呼,也就是顯示的向Spring注冊

  • 如果不掃描包坏快,就需要手動配置bean

  • 如果不加注解驅動,則注入的值為null憎夷!

10.6 基于Java類進行配置

JavaConfig 原來是 Spring 的一個子項目莽鸿,它通過 Java 類的方式提供 Bean 的定義信息,在 Spring4 的版本拾给, JavaConfig 已正式成為 Spring4 的核心功能 祥得。

測試:

1、編寫一個實體類蒋得,Dog

@Component  //將這個類標注為Spring的一個組件级及,放到容器中!
public class Dog {
   public String name = "dog";
}

2额衙、新建一個config配置包饮焦,編寫一個MyConfig配置類

@Configuration  //代表這是一個配置類
public class MyConfig {

   @Bean //通過方法注冊一個bean怕吴,這里的返回值就Bean的類型,方法名就是bean的id县踢!
   public Dog dog(){
       return new Dog();
  }

}

3转绷、測試

@Test
public void test2(){
   ApplicationContext applicationContext =
           new AnnotationConfigApplicationContext(MyConfig.class);
   Dog dog = (Dog) applicationContext.getBean("dog");
   System.out.println(dog.name);
}

導入其他配置如何做呢?

1硼啤、我們再編寫一個配置類议经!

@Configuration  //代表這是一個配置類
public class MyConfig2 {
}

2、在之前的配置類中我們來選擇導入這個配置類

@Configuration
@Import(MyConfig2.class)  //導入合并其他配置類谴返,類似于配置文件中的 inculde 標簽
public class MyConfig {

   @Bean
   public Dog dog(){
       return new Dog();
  }

}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末爸业,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子亏镰,更是在濱河造成了極大的恐慌扯旷,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件索抓,死亡現場離奇詭異钧忽,居然都是意外死亡,警方通過查閱死者的電腦和手機逼肯,發(fā)現死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門耸黑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人篮幢,你說我怎么就攤上這事大刊。” “怎么了三椿?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵缺菌,是天一觀的道長。 經常有香客問我搜锰,道長伴郁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任蛋叼,我火速辦了婚禮焊傅,結果婚禮上,老公的妹妹穿的比我還像新娘狈涮。我一直安慰自己狐胎,他們只是感情好,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布歌馍。 她就那樣靜靜地躺著握巢,像睡著了一般。 火紅的嫁衣襯著肌膚如雪骆姐。 梳的紋絲不亂的頭發(fā)上镜粤,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天捏题,我揣著相機與錄音,去河邊找鬼肉渴。 笑死公荧,一個胖子當著我的面吹牛,可吹牛的內容都是我干的同规。 我是一名探鬼主播循狰,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼券勺!你這毒婦竟也來了绪钥?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤关炼,失蹤者是張志新(化名)和其女友劉穎程腹,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體儒拂,經...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡寸潦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了社痛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片见转。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蒜哀,靈堂內的尸體忽然破棺而出斩箫,到底是詐尸還是另有隱情,我是刑警寧澤撵儿,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布乘客,位于F島的核電站,受9級特大地震影響统倒,放射性物質發(fā)生泄漏寨典。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一房匆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧报亩,春花似錦浴鸿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至劲件,卻和暖如春掸哑,著一層夾襖步出監(jiān)牢的瞬間约急,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工苗分, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留厌蔽,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓摔癣,卻偏偏與公主長得像奴饮,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子择浊,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內容