javascript
Spring学习总结一
Spring框架IoC與DI思想及應用
- Spring學習總結一
- 1、Spring是什么
- 2、Spring的優點
- 2.1、關鍵概念
- 2.2、Spring的優點
- 3、Spring的架構圖
- 3.1、核心容器:包括 Core 、 Beans 、 Context 、 EL 模塊
- 3.2、AOP 、 Aspects 模塊:
- 4、Spring的應用場景
- 4.1、典型 Web 應用程序應用場景
- 4.2、遠程訪問應用場景
- 4.3、EJB 應用場景
- 5、Spring的入門案例
- 5.1、下載并導入Spring核心的jar
- 5.2、創建一個對象
- 5.3、配置applicationContext.xml
- 5.4、測試
- 6、控制反轉(IoC)
- 6.1、什么是控制反轉
- 6.2、控制反轉容器
- 6.3、第一個案例的哪個部分用到控制反轉?
- 7、依賴注入(DI)
- 7.1、什么是依賴注入?
- 7.2、案例中哪里用到了依賴注入?
- 7.3、注入的屬性如果是一個bean,應該怎么編寫xml?
- 8、更多依賴注入的方法
- 8.1、p命名空間
- 8.2、屬性注入
- 8.3、構造函數注入
- 8.3.1、修改Address類
- 8.3.2、修改User類
- 8.3.3、修改struts.xml
- 8.3.4、測試
- 8.4、集合屬性注入
- 8.4.1、編寫CollectionTest類
- 8.4.2、編寫struts.xml
- 8.4.3、測試
- 9、bean的作用域
- 10、注解開發
- 10.1、在applicationContext.xml中開啟注解掃描器
- 10.2、在交給spring控制的bean上面寫注解
- 10.2.1、Address類
- 10.2.2、User類
- 10.2.3、UserDao類
- 10.2.4、UserService類
- 10.2.5、UserController類
- 10.2.6、測試
- 參考
Spring學習總結一
以下幾點:
1、Spring是什么
Spring 是一個開源的輕量級 Java SE( Java 標準版本)/Java EE( Java 企業版本)開發應用框架,其目的是用于簡化企業級應用程序開發。在傳統應用程序開發中,一個完整的應用是由一組相互協作的對象組成的。所以開發一個應用除了要開發業務邏輯之外,最多的是關注使這些對象協作來完成所需功能的同時,實現低耦合、高內聚。所以,業務邏輯開發是不可避免的。如果有個框架可以幫我們來創建對象及管理這些對象之間的依賴關系,能通過配置方式來創建對象,管理對象之間依賴關系,我們不需要通過工廠和生成器來創建及管理對象之間的依賴關系,這樣我們必然會減少許多工作量,加快開發。Spring 框架問世之初主要就是來完成這個功能。
Spring 框架除了幫我們管理對象及其依賴關系,還提供像通用日志記錄、性能統計、安全控制、異常處理等面向切面的能力,可以幫我們管理最頭疼的數據庫事務,同時,它本身提供了一套簡單的 JDBC 訪問實現,能與第三方數據庫訪問框架集成(如 Hibernate、JPA ),與各種 Java EE 技術整合(如 Java Mail、任務調度等等),提供一套自己的 web 層框架 Spring MVC 、而且還能非常簡單的與第三方 web 框架集成。從這里我們可以認為 Spring 是一個超級粘合平臺,除了自己提供功能外,還提供粘合其他技術和框架的能力,從而使我們可以更自由的選擇到底使用什么技術進行開發。而且不管是 JAVA SE( C/S 架構)應用程序還是 JAVA EE( B/S 架構)應用程序都可以使用這個平臺進行開發。
2、Spring的優點
Spring 能幫助我們簡化應用程序開發,幫助我們創建和組裝對象,為我們管理事務,簡單的 MVC 框架,可以把 Spring 看作是一個超級粘合平臺,能把很多技術整合在一起,形成一個整體,使系統結構更優良、性能更出眾,從而加速我們程序開發,有如上優點,我們沒有理由不考慮使用它。
2.1、關鍵概念
2.2、Spring的優點
3、Spring的架構圖
簡單來看,主要部分就是Core Container這個部分!
3.1、核心容器:包括 Core 、 Beans 、 Context 、 EL 模塊
3.2、AOP 、 Aspects 模塊:
4、Spring的應用場景
Spring 可以應用到許多場景,從最簡單的標準 Java SE 程序到企業級應用程序都能使用 Spring 來構建。以下介紹幾個比較流行的應用場景:
4.1、典型 Web 應用程序應用場景
4.2、遠程訪問應用場景
4.3、EJB 應用場景
5、Spring的入門案例
需要做的幾件事情:
5.1、下載并導入Spring核心的jar
Spring官方下載地址
隨便下載一個,建議下載4…以上的,3的版本好像并不支持jdk1.8。
還需要一個依賴的jar包,Spring依賴的logging下載地址
5.2、創建一個對象
package com.csa.domain;public class User {private String username;private Integer age;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "User [username=" + username + ", age=" + age + "]";} }5.3、配置applicationContext.xml
注意我是放在src下面:
<?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.csa.domain.User"><!-- 依賴注入(DI) --><property name="username" value="hello"></property><property name="age" value="18"></property></bean></beans>5.4、測試
package com.csa.app;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.domain.User;public class App {@Testpublic void app() {// 1.加載applicationContext.xmlString xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);// 2.獲取user的bean --> 也叫控制反轉(IoC)!User user = (User) applicationContext.getBean("user");System.out.println(user);} }結果:
6、控制反轉(IoC)
幾個問題:
6.1、什么是控制反轉
IoC 不是一種技術,只是一種思想,一個重要的面向對象編程的法則,它能指導我們如何設計出松耦合、更優良的程序。傳統應用程序都是由我們在類內部主動創建依賴對象,從而導致類與類之間高耦合,難于測試;有了IoC容器后,把創建和查找依賴對象的控制權交給了容器,由容器進行注入組合對象,所以對象與對象之間是松散耦合,這樣也方便測試,利于功能復用,更重要的是使得程序的整個體系結構變得非常靈活。
其實 IoC 對編程帶來的最大改變不是從代碼上,而是從思想上,發生了“主從換位”的變化。應用程序原本是老大,要獲取什么資源都是主動出擊,但是在 IoC/DI 思想中,應用程序就變成被動的了,被動的等待 IoC 容器來創建并注入它所需要的資源了。
IoC 很好的體現了面向對象設計法則之一的好萊塢法則:“別找我們,我們找你”;即由 IoC 容器幫對象找相應的依賴對象并注入,而不是由對象主動去找。
6.2、控制反轉容器
IoC 容器就是具有依賴注入(DI在下面會說明到)功能的容器,IoC 容器負責實例化、定位、配置應用程序中的對象及建立這些對象間的依賴。 應用程序無需直接在代碼中 new 相關的對象,應用程序由 IoC 容器進行組裝。在 Spring 中 BeanFactory 是 IoC 容器的實際代表者。
Spring IoC 容器如何知道哪些是它管理的對象呢?
這就**需要配置文件,Spring IoC 容器通過讀取配置文件中的配置元數據,通過元數據對應用中的各個對象進行實例化及裝配。**一般使用基于 xml 配置文件進行配置元數據,而且 Spring 與配置文件完全解耦的,可以使用其他任何可能的方式進行配置元數據,比如注解、基于 java 文件的、基于屬性文件的配置都可以。
在 Spring Ioc 容器的代表就是 org.springframework.beans 包中的 BeanFactory 接口, BeanFactory 接口提供了 IoC 容器最基本功能;而 org.springframework.context 包下的 ApplicationContext 接口擴展了 BeanFactory ,還提供了與Spring AOP 集成、國際化處理、事件傳播及提供不同層次的 context 實現 (如針對 web 應用的 WebApplicationContext )。簡單說, BeanFactory 提供了 IoC 容器最基本功能,而 ApplicationContext 則增加了更多支持企業級功能支持。 ApplicationContext 完全繼承 BeanFactory ,因而 BeanFactory 所具有的語義也適用于 ApplicationContext。
6.3、第一個案例的哪個部分用到控制反轉?
applicationContext.xml中配置了一個User的bean,說明User的管理權被applicationContext.xml給奪走。簡單的說,User的獲取交給Spring容器來處理。也就是說配置application其實就是配置了一個Spring,配置了Spring其實就配置了一個IoC。 IoC主要又是一種思想!真正起到作用的是我們導入的spring的bean這個jar。
上面2附圖合起來就算是一個控制反轉的例子!
7、依賴注入(DI)
解決下面幾個問題:
7.1、什么是依賴注入?
DI—Dependency Injection,即“依賴注入”:是組件之間依賴關系由容器在運行期決定,形象的說,即由容器動態的將某個依賴關系注入到組件之中。 依賴注入的目的并非為軟件系統帶來更多功能,而是為了提升組件重用的頻率,并為系統搭建一個靈活、可擴展的平臺。通過依賴注入機制,我們只需要通過簡單的配置,而無需任何代碼就可指定目標需要的資源,完成自身的業務邏輯,而不需要關心具體的資源來自何處,由誰實現。
理解 DI 的關鍵是:“誰依賴誰,為什么需要依賴,誰注入誰,注入了什么”,那我們來深入分析一下:
7.2、案例中哪里用到了依賴注入?
7.3、注入的屬性如果是一個bean,應該怎么編寫xml?
假設User多了Address屬性!
Address類
修改applicationContext.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.csa.domain.User"><!-- 依賴注入(DI) --><property name="username" value="hello"></property><property name="age" value="18"></property><!-- 注意不是value,而是ref哦 --><property name="address" ref="address"></property></bean><bean id="address" class="com.csa.domain.Address"><property name="province" value="AA"></property><property name="city" value="BB"></property></bean></beans>測試結果如下:
package com.csa.app;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.domain.User;public class App {@Testpublic void app() {// 1.加載applicationContext.xmlString xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);// 2.獲取user的bean --> 也叫控制反轉(IoC)!User user = (User) applicationContext.getBean("user");System.out.println(user);} }8、更多依賴注入的方法
還有其他幾種常見的依賴注入的方法:
8.1、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:p="http://www.springframework.org/schema/p"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user" class="com.csa.domain.User"><!-- 依賴注入(DI) --><property name="username" value="hello"></property><property name="age" value="18"></property><!-- 注意不是value,而是ref哦 --><property name="address" ref="address"></property></bean><!-- 注意約束上面加了一個xmlns:p的內容,并且這個時候是以"p:屬性名"在bean中作為屬性名的形式注入的 --><bean id="address" class="com.csa.domain.Address" p:province="CC" p:city="DD"></bean></beans>最后測試:
package com.csa.app;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.domain.User;public class App {@Testpublic void app() {// 1.加載applicationContext.xmlString xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);// 2.獲取user的bean --> 也叫控制反轉(IoC)!User user = (User) applicationContext.getBean("user");System.out.println(user);} }8.2、屬性注入
<?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.csa.domain.User"><!-- 依賴注入(DI) --><property name="username" value="hello"></property><property name="age" value="18"></property><!-- set方法注入 --><property name="address"><bean class="com.csa.domain.Address"><property name="province" value="hello"></property><property name="city" value="world"></property></bean></property></bean></beans>8.3、構造函數注入
需要做下面4步:
8.3.1、修改Address類
package com.csa.domain;public class Address {private String province;private String city;public Address(String province, String city) {super();this.province = province;this.city = city;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}@Overridepublic String toString() {return "Address [province=" + province + ", city=" + city + "]";} }8.3.2、修改User類
package com.csa.domain;public class User {private String username;private Integer age;private Address address;public User(String username, Integer age, Address address) {super();this.username = username;this.age = age;this.address = address;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}@Overridepublic String toString() {return "User [username=" + username + ", age=" + age + ", address=" + address + "]";} }8.3.3、修改struts.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.csa.domain.User"><!-- 第一種寫法(我一般都這樣玩):name指向的是屬性名,value是對應的值 --><constructor-arg name="username" value="hello"></constructor-arg><constructor-arg name="age" value="18"></constructor-arg><!-- 這樣注入一個依賴,我是有點不太適應的! --><constructor-arg name="address"><bean class="com.csa.domain.Address"><!-- 第二種寫法(我一般不這樣玩!):index按照全部參數情況下的第幾個參數 --><!-- 按這個例子來說,第一個String是"省份" --><constructor-arg index="0" value="hello"></constructor-arg><!-- 第二個是"城市" --><constructor-arg index="1" value="world"></constructor-arg></bean></constructor-arg></bean> </beans>8.3.4、測試
package com.csa.app;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.domain.User;public class App {@Testpublic void app() {// 1.加載applicationContext.xmlString xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);// 2.獲取user的bean --> 也叫控制反轉(IoC)!User user = (User) applicationContext.getBean("user");System.out.println(user);} }測試結果:
8.4、集合屬性注入
做以下幾個步驟:
8.4.1、編寫CollectionTest類
package com.csa.domain;import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set;public class CollectionTest {private Object[] arr;private List<Object> list;private Set<Object> set;private Map<String,Object> map;private Properties pros;public Object[] getArr() {return arr;}public void setArr(Object[] arr) {this.arr = arr;}public List<Object> getList() {return list;}public void setList(List<Object> list) {this.list = list;}public Set<Object> getSet() {return set;}public void setSet(Set<Object> set) {this.set = set;}public Map<String, Object> getMap() {return map;}public void setMap(Map<String, Object> map) {this.map = map;}public Properties getPros() {return pros;}public void setPros(Properties pros) {this.pros = pros;}@Overridepublic String toString() {return "CollectionTest [\r\narr=" + Arrays.toString(arr) + ", \r\nlist=" + list + ",\r\nset=" + set + ",\r\nmap=" + map+ ",\r\npros=" + pros + "]";} }8.4.2、編寫struts.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.csa.domain.User"><!-- 第一種寫法:name指向的是屬性名,value是對應的值 --><constructor-arg name="username" value="hello"></constructor-arg><constructor-arg name="age" value="18"></constructor-arg><constructor-arg name="address"><bean class="com.csa.domain.Address"><!-- 第二種寫法:index按照全部參數情況下的第幾個參數 --><!-- 按這個例子來說,第一個String是"省份" --><constructor-arg index="0" value="hello"></constructor-arg><!-- 第二個是城市 --><constructor-arg index="1" value="world"></constructor-arg></bean></constructor-arg></bean><bean id="address" class="com.csa.domain.Address"><constructor-arg index="0" value="hello"></constructor-arg><constructor-arg index="1" value="spring"></constructor-arg></bean><bean id="collectionBean" class="com.csa.domain.CollectionTest"><property name="arr"><array><value>1</value><ref bean="user"/><bean class="com.csa.domain.Address"><constructor-arg index="0" value="spring"></constructor-arg><constructor-arg index="1" value="arr"></constructor-arg></bean></array></property><property name="list"><list><value>2</value><ref bean="user"/><bean class="com.csa.domain.Address"><constructor-arg index="0" value="spring"></constructor-arg><constructor-arg index="1" value="list"></constructor-arg></bean></list></property><property name="set"><set><value>3</value><ref bean="address"/><bean class="com.csa.domain.Address"><constructor-arg index="0" value="spring"></constructor-arg><constructor-arg index="1" value="set"></constructor-arg></bean></set></property><property name="map"><map><entry key="1" value="4"></entry><entry key="2" value-ref="address"></entry><entry key="3"><bean class="com.csa.domain.Address"><constructor-arg index="0" value="spring"></constructor-arg><constructor-arg index="1" value="set"></constructor-arg></bean></entry></map></property><!-- Properties 類型類似于Map,但是Properties只能是字符串--><property name="pros"><props><prop key="1">1</prop><prop key="2">2</prop><prop key="3">3</prop></props></property></bean></beans>8.4.3、測試
package com.csa.app;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.domain.User;public class App {@Testpublic void app() {// 1.加載applicationContext.xmlString xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);// 2.獲取user的bean --> 也叫控制反轉(IoC)!CollectionTest collection = (CollectionTest) applicationContext.getBean("collectionBean");System.out.println(collection);} }測試結果:
9、bean的作用域
使用方法就是:<bean name="bean名字" class="包名.類名" scope="作用域"></bean>。
在 Spring 中,支持以下5 種類型的作用域:
注:大多數情況下,你可能只需要處理 Spring 的核心作用域 — 單例模式( singleton )和原型模式( prototype ),默認情況下,作用域是單例模式。
10、注解開發
注解開發需要做下面幾個步驟:
10.1、在applicationContext.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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 第一種:太麻煩 --><context:component-scan base-package="com.csa.domain,com.csa.dao,com.csa.service,com.csa.controller"></context:component-scan><!-- 第二種:常用 --><!-- <context:component-scan base-package="com.csa"></context:component-scan> --></beans>10.2、在交給spring控制的bean上面寫注解
需要寫的類,還需要注意,每個類不能允許有構造并且基本類型需要編寫get/set方法:
10.2.1、Address類
package com.csa.domain;import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; //等價于<bean name="address" class="com.csa.domain.Address"></bean> @Component(value="address") public class Address {// 等價于<property name="province" value="hello"></property>@Value(value="hello")private String province;// 等價于<property name="city" value="spring"></property>@Value(value="spring")private String city;public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}@Overridepublic String toString() {return "Address [province=" + province + ", city=" + city + "]";} }10.2.2、User類
package com.csa.domain;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.Component;// 等價于<bean name="user" class="com.csa.domain.User"></bean> @Component(value="user") public class User {// 等價于<property name="username" value="小A"></property>@Value(value="小A")private String username;// 等價于<property name="age" value="18"></property>@Value(value="18")private Integer age;// 等價于<property name="age" value="18"></property>@Autowired@Qualifier(value="address")private Address address;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}@Overridepublic String toString() {return "User [username=" + username + ", age=" + age + ", \r\n\taddress=" + address + "]";} }10.2.3、UserDao類
package com.csa.dao;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Repository;import com.csa.domain.User;// 等同于<bean name="userDao" class="com.csa.dao.UserDao"></bean> @Repository(value="userDao") public class UserDao {// 這個相當于獲取一個name為user的bean@Autowired// 不寫,默認取user,寫了更清晰@Qualifier(value="user")private User user;public void printUser() {System.out.println(user);} }10.2.4、UserService類
package com.csa.service;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;import com.csa.dao.UserDao;//等價于<bean name="userService" class="com.csa.service.UserService"></bean> @Service(value="userService") public class UserService {@Autowiredprivate UserDao userDao;public void printUser() {userDao.printUser();}}10.2.5、UserController類
package com.csa.controller;import javax.annotation.Resource;import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller;import com.csa.service.UserService; // 等價于<bean name="userController" class="com.csa.controller.UserController" scope="singleton"></bean> @Controller(value="userController") @Scope(value="singleton") public class UserController {// 第一種方式:// 這個相當于獲取一個name為userService的bean// @Autowired// @Qualifier(value="userService")// 第二種方式:// @Resource(name="userService")// 第三種方式:不寫name,則name的默認"類名首字母小寫"@Resourceprivate UserService userService;public void printUser() {userService.printUser();}}10.2.6、測試
package com.csa.app;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.controller.UserController;public class App {@Testpublic void app() {// 1.加載applicationContext.xmlString xmlPath = "applicationContext.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserController userController = (UserController) applicationContext.getBean("userController");userController.printUser();} }測試結果:
參考
實驗樓
總結
以上是生活随笔為你收集整理的Spring学习总结一的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 公司让我试岗
- 下一篇: 2020年中国住宿业市场网络口碑报告