Java学习笔记11-1——Spring5
文章目錄
- 1.簡介
- 組成
- 拓展
- 2.控制反轉(IoC)
- IoC例子
- IoC本質
- 3.Hello,Spring
- demo1
- 修改user例子的代碼
- 思考
- 4.IoC創建對象的方式
- 通過無參構造的方式
- 通過有參構造的方式
- 5.Spring配置
- alias 設置別名
- Bean的配置
- import
- 6.依賴注入(DI)
- 構造器注入
- set方式注入【重點】
- 普通常量注入
- Bean注入
- 數組注入
- List注入
- Map注入
- Set注入
- Null注入
- Properties注入
- 其他方式注入
- p命名空間注入
- c命名空間注入
- Bean的作用域
- Singleton單例模式
- Prototype原型模式
1.簡介
Spring是一個輕量級的控制反轉(IoC)和面向切面(AOP)的容器(框架)。
官網 : http://spring.io/
官方下載地址 : https://repo.spring.io/libs-release-local/org/springframework/spring/
GitHub : https://github.com/spring-projects
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.5.RELEASE</version> </dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.2.3.RELEASE</version> </dependency>優點:
1、Spring是一個開源免費的框架
2、Spring是一個輕量級的非侵入式的框架
組成
Spring 框架是一個分層架構,由 7 個定義良好的模塊組成。Spring 模塊構建在核心容器之上,核心容器定義了創建、配置和管理 bean 的方式。
組成 Spring 框架的每個模塊(或組件)都可以單獨存在,或者與其他一個或多個模塊聯合實現。每個模塊的功能如下:
- 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要組件是BeanFactory,它是工廠模式的實現。BeanFactory 使用控制反轉(IOC)模式將應用程序的配置和依賴性規范與實際的應用程序代碼分開。
- Spring 上下文:Spring 上下文是一個配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企業服務,例如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。
拓展
SpringBoot與SpringCloud
- SpringBoot 是 Spring 的一套快速配置腳手架,可以基于SpringBoot 快速開發單個微服務;
- SpringCloud是基于SpringBoot實現的;
- SpringBoot專注于快速、方便集成的單個微服務個體,SpringCloud關注全局的服務治理框架;
- SpringBoot使用了約束優于配置的理念,很多集成方案已經幫你選擇好了,能不配置就不配置 ,
- SpringCloud很大的一部分是基于SpringBoot來實現,SpringBoot可以離開SpringCloud獨立使用開發項目,但是SpringCloud離不開SpringBoot,屬于依賴的關系。
- SpringBoot在SpringClound中起到了承上啟下的作用,如果你要學習SpringCloud必須要學習SpringBoot。
2.控制反轉(IoC)
IoC例子
我們先用我們原來的方式寫一段代碼:
1、先寫一個UserDao接口
2、再去寫UserDao的實現類UserDaoImpl
public class UserDaoImpl implements UserDao {@Overridepublic void getUser() {System.out.println("獲取用戶數據");} }3、然后去寫業務接口UserService
public interface UserService {public void getUser(); }4、最后寫Service的實現類
public class UserServiceImpl implements UserService {private UserDao userDao = new UserDaoImpl();@Overridepublic void getUser() {userDao.getUser();} }5、測試(模擬使用業務)
@Test public void test(){UserService service = new UserServiceImpl();service.getUser(); }6、現在把UserDao的實現類增加一個(模擬現實中不同需求)
public class UserDaoMySqlImpl implements UserDao {@Overridepublic void getUser() {System.out.println("MySQL獲取用戶數據");} }7、緊接著如果要使用MySQL的話,我們就需要去Service實現類里面修改new的接口
public class UserServiceImpl implements UserService {private UserDao userDao = new UserDaoMySqlImpl();@Overridepublic void getUser() {userDao.getUser();} }8、再假設, 我們再增加一個UserDao的實現類
public class UserDaoOracleImpl implements UserDao {@Overridepublic void getUser() {System.out.println("Oracle獲取用戶數據");} }那么如果我們要使用Oracle,又需要去Service實現類里面修改對應的實現。假設我們的這種需求非常大, 這種方式就根本不適用了,甚至反人類。每次變動都需要修改大量代碼。這種設計的耦合性太高。
如何去解決呢 ?
我們可以在需要用到他的地方,不去實現它,而是留出一個接口,利用set,我們去代碼里修改下:
public class UserServiceImpl implements UserService {private UserDao userDao; // 利用set實現public void setUserDao(UserDao userDao) {this.userDao = userDao;}@Overridepublic void getUser() {userDao.getUser();} }此時,有了set方法就可以在調用的時候由用戶選擇調用的接口
@Test public void test(){UserServiceImpl service = new UserServiceImpl();service.setUserDao( new UserDaoMySqlImpl() );service.getUser();//那我們現在又想用Oracle去實現呢service.setUserDao( new UserDaoOracleImpl() );service.getUser(); }以前所有東西都是由程序去進行控制創建,而現在是由我們自行控制創建對象,把主動權交給了調用者 / 用戶。程序不用去管怎么創建,怎么實現了。它只負責提供一個接口。
這種思想從本質上解決了問題,我們程序員不再去管理對象的創建了,更多去關注業務的實現。耦合性大大降低。這也就是IoC的原型。
IoC本質
控制反轉IoC(Inversion of Control),是一種設計思想,DI(依賴注入)是實現IoC的一種方法,也有人認為DI只是IoC的另一種說法。
沒有IoC的程序中 , 我們使用面向對象編程 , 對象的創建與對象間的依賴關系完全硬編碼在程序中,對象的創建由程序自己控制,
控制反轉后將對象的創建轉移給第三方,個人認為所謂控制反轉就是:獲得依賴對象的方式反轉了。
IoC是Spring框架的核心內容,使用多種方式完美的實現了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置實現IoC。
Spring容器在初始化時先讀取配置文件,根據配置文件或元數據創建與組織對象存入容器中,程序使用時再從IoC容器中取出需要的對象。
采用XML方式配置Bean的時候,Bean的定義信息是和實現分離的,而采用注解的方式可以把兩者合為一體,Bean的定義信息直接以注解的形式定義在實現類中,從而達到了零配置的目的。
控制反轉是一種通過描述(XML或注解)并通過第三方去生產或獲取特定對象的方式。在Spring中實現控制反轉的是IoC容器,其實現方法是依賴注入(Dependency Injection,DI)。
3.Hello,Spring
demo1
1、編寫一個Hello實體類
public class Hello {private String myName;@Overridepublic String toString() {return "Hello{" +"myName='" + myName + '\'' +'}';}public String getMyName() {return myName;}public void setMyName(String myName) {this.myName = myName;} }2、編寫我們的spring文件 , 這里我們命名為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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!--bean就是java對象 , 由Spring創建和管理--><!--使用spring來創建對象,在spring中這些稱為bean類型 變量名 = new 類型();Hello hello = new Hello();id:變量名class: new的對象property: 給對象中的屬性設置值--><bean id="hello" class="pojo.Hello"><property name="myName" value="Hello, Spring"/></bean></beans>3、我們可以去進行測試了
@Testpublic void test(){// 獲取spring的上下文對象 解析beans.xml文件,生成管理相應的Bean對象ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");// getBean : 參數即為spring配置文件中bean的id// 這就是控制反轉,不需要new對象,直接從context里面拿就行Hello hello = (Hello) context.getBean("hello");System.out.println(hello.toString());} }修改user例子的代碼
在user例子中, 新增一個Spring配置文件beans.xml
<bean id="MysqlImpl" class="dao.UserDaoMySqlImpl"/><bean id="OracleImpl" class="dao.UserDaoOracleImpl"/><bean id="ServiceImpl" class="service.UserServiceImpl"><!--注意: 這里的name并不是屬性 , 而是set方法后面的那部分 , 首字母小寫--><!--引用另外一個bean , 不是用value 而是用 ref--><property name="userDao" ref="OracleImpl"/><!--具體使用哪個接口這里可以直接配置--></bean> @Test public void test2(){ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");UserServiceImpl serviceImpl = (UserServiceImpl) context.getBean("ServiceImpl");serviceImpl.getUser(); }思考
Hello 對象是誰創建的 ?
- 是由Spring創建的
Hello 對象的屬性是怎么設置的 ?
- 是由Spring容器設置的
這個過程就叫控制反轉 :
- 控制 : 誰來控制對象的創建 , 傳統應用程序的對象是由程序本身控制創建的 , 使用Spring后 , 對象是由Spring來創建的
- 反轉 : 程序本身不創建對象 , 而變成被動的接收對象
依賴注入 : 就是利用set方法來進行注入的
IoC是一種編程思想,由主動的編程變成被動的接收
可以通過new ClassPathXmlApplicationContext去瀏覽一下底層源碼
4.IoC創建對象的方式
通過無參構造的方式
@Testpublic void test(){ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");// 這時調用了User的無參構造//User user = (User) context.getBean("user");} }輸出
通過有參構造的方式
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 );} } <!-- 第一種根據下標賦值 --><!--<bean id="userT" class="pojo.UserT"><constructor-arg index="0" value="張三"/></bean> --><!-- 第二種根據參數名字設置 --><bean id="userT" class="pojo.UserT"><!-- name指參數名 --><constructor-arg name="name" value="張三"/></bean><!-- 第三種根據參數類型設置(不推薦使用) --><!--<bean id="userT" class="pojo.UserT"><constructor-arg type="java.lang.String" value="張三"/></bean> --> @Testpublic void testT(){ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); // UserT user = (UserT) context.getBean("userT"); // user.show();} }輸出
可見把前一個例子的User也new了對象,所以在配置文件加載的時候,會把其中所有管理的對象都初始化(前一個例子的輸出沒有輸出有參構造是因為當時還沒創建UserT)
5.Spring配置
alias 設置別名
<bean id="userT" class="pojo.UserT"><!-- name指參數名 --><constructor-arg name="name" value="張三"/></bean><!--設置別名:在獲取Bean的時候可以使用別名獲取--><alias name="userT" alias="userNew"/> UserT user = (UserT) context.getBean("userNew");Bean的配置
-
id 是bean的標識符,要唯一,如果沒有配置id,name就是默認標識符
-
如果配置id,又配置了name,那么name是別名
-
name可以設置多個別名,可以用逗號,分號,空格隔開
-
如果不配置id和name,可以根據applicationContext.getBean(.class)獲取對象;
-
class是bean的全限定名,即:包名+類名
import
一般用于團隊開發,它可以將多個配置文件,導入合并為一個
<import resource="beans2.xml"/> <import resource="beans3.xml"/> <import resource="beans4.xml"/> ...6.依賴注入(DI)
構造器注入
參考上面,已經說過
set方式注入【重點】
依賴:bean對象的創建依賴于容器
注入:bean對象中的所有屬性,由容器來注入
要求被注入的屬性 , 必須有set方法 , set方法的方法名由set + 屬性首字母大寫 , 如果屬性是boolean類型 , 沒有set方法 , 是 is
先建立兩個pojo類作為例子
Student:
Address:
public class Address {private String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;} }普通常量注入
<bean id="student" class="pojo.Student"><property name="name" value="小明"/></bean> @Testpublic void test01(){ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");Student student = (Student) context.getBean("student");System.out.println(student.getName());}Bean注入
使用ref來引用
<bean id="addr" class="pojo.Address"><property name="address" value="重慶"/></bean><bean id="student" class="pojo.Student"><property name="name" value="小明"/><property name="address" ref="addr"/></bean>數組注入
<property name="books"><array><value>西游記</value><value>紅樓夢</value><value>水滸傳</value></array></property>List注入
<property name="hobbies"><list><value>聽歌</value><value>看電影</value><value>爬山</value></list></property>Map注入
<property name="card"><map><entry key="身份證" value="123312341234123412"/><entry key="銀行卡" value="1456682255511"/></map></property>Set注入
<property name="games"><set><value>LOL</value><value>BOB</value><value>COC</value></set></property>Null注入
<property name="wife"><null/></property>Properties注入
<property name="info"><props><prop key="學號">20190604</prop><prop key="性別">男</prop><prop key="姓名">小明</prop></props></property>測試結果:
其他方式注入
創建一個User類
public class User {private String name;private int age;public User() {}public User(String name, int age) {this.name = name;this.age = age;}public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';} }p命名空間注入
P(屬性: properties)
直接注入屬性的值
導入約束 : xmlns:p=“http://www.springframework.org/schema/p”
<?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:c="http://www.springframework.org/schema/c"xmlns:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="pojo.User" p:name="張三" p:age="18"/></beans>c命名空間注入
C(構造: Constructor)
通過構造器注入
導入約束 : xmlns:c=“http://www.springframework.org/schema/c”
<bean id="user" class="pojo.User" c:name="張三" c:age="18"/>測試
@Testpublic void test02(){ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");User user =context.getBean("user",User.class);User user2 =context.getBean("user2",User.class);System.out.println(user+" "+user2);} }Bean的作用域
幾種作用域中,request、session作用域僅在基于web的應用中使用(不必關心你所采用的是什么web應用框架),只能用在基于web的Spring ApplicationContext環境。
Singleton單例模式
在創建起容器時就同時自動創建了一個bean的對象,不管你是否使用,他都存在了,每次獲取到的對象都是同一個對象。
單例模式是Spring的默認機制
<bean id="user" class="pojo.User" p:name="張三" p:age="18" scope="singleton"/>單例模式也就是只new一次對象,之后getBean的都直接獲取第一次new的對象
@Testpublic void test02(){ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");User user = context.getBean("user",User.class);User user2 = context.getBean("user2",User.class);System.out.println(user==user2); //true} }Prototype原型模式
每次從容器中get的時候,都會產生一個新對象
<bean id="user" class="pojo.User" p:name="張三" p:age="18" scope="Prototype"/> @Testpublic void test02(){ApplicationContext context = new ClassPathXmlApplicationContext("userBeans.xml");User user = context.getBean("user",User.class);User user2 = context.getBean("user2",User.class);System.out.println(user==user2); //false} }總結
以上是生活随笔為你收集整理的Java学习笔记11-1——Spring5的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HYSBZ - 1050(旅行comf
- 下一篇: Java学习笔记13-1——Spring