Spring
簡介
spring,英文單詞為春天,表示為軟體行業帶來了春天,
2002年,首次推出了Spring框架的雛形:interface21框架,官網為:www.interface21.io但是現在進去時間略長,
Spring框架是以上面這個框架為基礎重新設計,并不斷對其進行改進豐富其內涵,在2004年3月24日發布了1.0正式版本,
框架的創始人是Rod Johnson,此人原先是悉尼大學音樂學的博士,讓人大吃一驚,
Spring的理念:從官網進入??頂部導航欄projects??Spring framework??Learn??手冊??歷史??設計理念
When you learn about a framework, it’s important to know not only what it does but what principles it follows. Here are the guiding principles of the Spring Framework:
Provide choice at every level. Spring lets you defer design decisions as late as possible. For example, you can switch persistence providers through configuration without changing your code. The same is true for many other infrastructure concerns and integration with third-party APIs.
Accommodate diverse perspectives. Spring embraces flexibility and is not opinionated about how things should be done. It supports a wide range of application needs with different perspectives.
Maintain strong backward compatibility. Spring’s evolution has been carefully managed to force few breaking changes between versions. Spring supports a carefully chosen range of JDK versions and third-party libraries to facilitate maintenance of applications and libraries that depend on Spring.
Care about API design. The Spring team puts a lot of thought and time into making APIs that are intuitive and that hold up across many versions and many years.
Set high standards for code quality. The Spring Framework puts a strong emphasis on meaningful, current, and accurate javadoc. It is one of very few projects that can claim clean code structure with no circular dependencies between packages.
這是官網上說的自身的特點:??

導包
搜索spring maven
到maven spring 搜索web mvc,現在也搜索不到,直接網站送上:
www.mvnrepository.com,進入網站后搜索web mvc,接著是點擊第一個,點擊最新的版本,里面有幾行代碼,復制到組態檔中就可以,
除了這個包,還需要一個jdbc,
http://www.java2s.com/Open-Source/Maven_Repository/Spring/spring-webmvc/spring_webmvc_2_5_1.htm
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>2.5.1</version>
</dependency>
介紹
官網:https://spring.io/projects/spring-framework
https://spring.io/projects/spring-framework#overview
官方下載地址:https://repo.spring.io/ui/native/release/org/springframework/spring
進入官網之后,https://docs.spring.io/spring-framework/docs/4.3.9.RELEASE/spring-framework-reference/html/
進入路徑沒理清楚,進入該網站后,尋找Distribution Zip Files,找到它的網站說明,就可以,
GitHub:https://github.com/spring-projects/spring-framework
優點
- Spring是一個開源的免費的框架(容器)
- Spring是一個輕量級的、非入侵式的框架
- 控制反轉(IOC),面向切面編程(AOP)(面試肯定會問)
- 支持事務的處理,對框架整合的支持,幾乎市面上所有的框架都支持,
總結:Spring是一個輕量級的控制反轉(IOC)和面向切面編程(AOP)的框架
組成

拓展
官網介紹說,現代化的Java開發,說白就是基于spring的開發,
Spring Boot
-
- 一個快速開發的腳手架,用了之后,只需要做一些簡單的配置,便可以快速開發一個網站
- 基于SpringBoot可以快速開發單個微服務
- 約定>配置
- Spring Cloud
- SpringCloud是基于SpringBoot實作的
因為現在大多數公司都在使用SpringBoot進行快速開發,學習SpringBoot的前提,需要完全掌握Spring及SpringMVC——這兩者具有承上啟下的作用,
缺點:發展過久,違背最初理念,配置繁瑣,直到SpringBoot才解放,人稱“配置地獄”,
IOC 理論指導
-
UserDao介面(在com.kuang.dao包中新建UserDao介面)
public interface UserDao { void GetUser(); } -
UserDaoImpl實作類(在com.kuang.dao包中新建UserDaoImpl實作類)
public class UserDaoImpl implements UserDao{ public void GetUser(){ System.out.println("默認獲取用戶資料"); } } -
UserService介面(在com.kuang.service包中新建UserService介面)
public interface UserService { void GetUser(); void setUserDao(UserDao userdao); } -
UserServiceImpl業務實作類(在com.kuang.service包中新建UserServiceImpl介面)
public class UserServiceImpl implements UserService {
// 業務層調Dao層,Java中除了繼承還有個組合的概念,用的話直接放過來就行,
// 下面這一行代碼,能不能解決這個問題,使得有不同的類,也可以用不同的方法,雖然是同一個名字,
private UserDao userDao;
// 利用Set動態進行值的注入
public void setUserDao( UserDao userDao){
this.userDao = userDao;
}
// 像這樣就是寫死的,真正呼叫的是業務層調Dao層,
public void GetUser(){
userDao.GetUser();
}
}

在我們之前的業務中,用戶的需求可能會影響我們原來的代碼,我們需要根據用戶的需求不停地修改代碼,如果程式代碼量十分大,修改一次的成本代價十分昂貴,
但是使用一個set介面實作,會實作控制反轉的效果,原先是我們來控制是使用哪個類執行,現在用戶只需要傳個引數,就可以動態的控制使用哪個類執行,

代碼:(同時介面也得宣告,否則沒法呼叫,)
private UserDao userDao;
// 利用Set動態進行值的注入
public void setUserDao( UserDao userDao){
this.userDao = userDao;
}
- 之前程式是主動創建物件,控制權在程式員手上,所以用戶的每個需求都會讓程式員改變代碼,利用set注入后,程式沒有主動性,而是變成被動的接收物件,
- 這種思想,從本質上解決了問題,程式員不必再管理物件的創建,系統的耦合性大大降低,可以更加專注的在業務的實作上,
- 業務層呼叫dao層,service呼叫的是dao層,
IOC本質
控制反轉(Inversion of Control)是一種設計思想,依賴注入是實作IOC的一種方法,也有人認為DI(依賴注入)只是IOC的另一種說法,沒有IOC的程式中(就是沒有控制反轉這樣一個概念),我們使用面向物件編程,物件的創建與物件間的依賴關系完全硬編碼在程式中,物件的創建由程式自己控制,控制反轉后將物件轉移給第三方,個人認為所謂控制反轉就是,獲得依賴物件的方式反轉了,
IOC是Spring框架的核心內容,使用多種方式完美的實作了IOC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置實作IOC,
Spring容器在初始化時先讀取組態檔,根據組態檔或者元資料創建或者組織物件存入容器中,程式使用時再從IOC容器中取出需要的物件,

采用XML方式配置Bean時,Bean的定義資訊和實作是分離的,而采用注解的方式可以把兩者合為一體,Bean的定義資訊直接以注解的形式定義在實作類中,從而達到了零配置的目的,
控制反轉是一種通過描述(XML或者注解)并通過第三方去生產或者獲取特定物件的方式,在Spring中實作控制反轉的是IOC容器,其實作方式是依賴注入,(Dependency Injection,DI)
HelloSpring
xml注解來源:https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/core.html#beans
Spring-02-helloSPring流程
如何實作流程:
創建一個新的模塊,spring-02-hellospring,接著創建com.kuang.dao包,新建hello類:
package com.kuang.pojo;
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
再新建beans.xml檔案,檔案中的內容由來:https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/core.html#beans
以下示例顯示了基于 XML 的配置元資料的基本結構:
中間的bean標簽洗掉,要自己寫,
<?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="..." > (1) (2)
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." >
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
這是自己寫的內容:
<!-- 使用Spring來創建物件,在Spring中這些都稱為Bean-->
<!-- 原先:型別 變數名 = new 型別();
Hello hello = new Hello();
現在:bean = 物件 new Hello();
id = 物件名;
class = new 的物件;
這里的str是普通屬性,用value即可,
當屬性標簽中,不是普通屬性,而是一個類屬性時,需要用到ref參考,
-->
<bean id="hello" >
<property name="str" value="https://www.cnblogs.com/jdpromptly/p/Spring"/>
</bean>
此時,類就映射為bean,id為hello,類中的屬性也隨之映射為value,
在測驗包中新建MyTest.java測驗:
第9行代碼是官方檔案指定,不能更改,
import com.kuang.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
// 獲取Spring中的背景關系物件
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//我們的物件現在都在Spring中的管理了,要使用,直接取出即可,
Hello hello = (Hello) context.getBean("hello");
System.out.println(hello.toString());
}
}
測驗結果:

根據這篇文章所說,Spring是一個將類放到容器中,映射為對應的bean,隨用隨取的框架,加深理解:https://blog.csdn.net/Yang_Hui_Liang/article/details/88977548
Spring-ioc-01流程
根據以上的Spring容器框架使用,現對之前的專案進行改動,
新建beans.xml,檔案中內容來源:https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/core.html#beans
把bean標簽洗掉,填為自己的內容:
<bean id="mysqlImpl" >
</bean>
<bean id="oracleImpl" >
</bean>
<bean id="userImpl" >
</bean>
<!--當屬性標簽中,不是普通屬性,而是一個類屬性時,需要用到ref參考,-->
<bean id="UserServiceImpl" >
<property name="userDao" ref="oracleImpl"/>
</bean>
在測驗類中進行測驗,其中,第9行代碼是官網指定,不能更改,
import com.kuang.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MTest {
public static void main(String[] args) {
// 獲取ApplicationContext,拿到Spring的容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 方法中獲取的是id
// 有了容器之后,為所欲為,
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
userServiceImpl.GetUser();
}
}
測驗結果:

在beans.xml檔案中更改不同的參考:測驗結果也會有不同
<bean id="UserServiceImpl" >
<property name="userDao" ref="userImpl"/>
結果:

更改:
<bean id="UserServiceImpl" >
<property name="userDao" ref="mysqlImpl"/>
結果:

思考問題
-
hello物件是由誰創建的?
-
hello物件是由Spring創建的
-
Hello物件是怎么設定的?
-
hello 物件是由Spring容器設定的
這個程序就叫控制反轉,我的理解是,本來用戶提出需求,程式員更改代碼完成需求,現在程式員先把代碼寫好,由用戶自己決定需求,直接在組態檔中進行修改即可,程式員不必每次在更換需求時更改大量代碼,
如果上述不理解,舉個例子去飯館吃飯,原先沒有控制反轉時,食客(用戶)想吃什么菜(需求),廚師(程式員)就做什么菜(改動對應的代碼),有了控制反轉后,現在飯館變成了自助餐廳,食客想吃什么,自取即可,廚師只需要提供食客想吃的菜品即可,把選擇權交給了食客,廚師就不必根據不同的食客點菜來單獨的炒菜,
如果還是不理解控制反轉,建議先多讀幾遍,爭取記住它的內容,接著實戰編程,相信會理解的,
以下是狂神的筆記,有一定的抽象性,結合例子來看更易理解,
控制:誰來控制物件的創建,傳統應用程式的物件是由程式本身控制創建的,使用Spring后,物件是由Spring來創建的,
反轉:程式本身不創建物件,而變成被動的接收物件,
依賴注入:就是利用set方法來進行注入,
IOC是一種編程思想,由主動地編程變成被動地接收,
可以通過newClassPathXmlApplicaitonContext去瀏覽一下底層原始碼,
至此,我們已不必再去程式中進行改動,需要實作不同的操作,只需要在xml組態檔中進行修改,總結IOC就是物件由Spring來創建、管理和裝配,
IOC創建檔案方式
準備:創建物件,寫入beans.xml,創建測驗類
創建User物件??
package com.kuang.pojo;
public class User {
public User() {
System.out.println("李豐平!");
}
public User(String name) {
this.name = name;
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void show(){
System.out.println("name = " + name+" ***");
}
}
寫入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" >
<property name="name" value="https://www.cnblogs.com/jdpromptly/p/李豐平"/>
</bean>
</beans>
撰寫測驗類??
import com.kuang.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 在getBean時,物件已經被創建,
User user = (User) context.getBean("user");
user.show();
}
}
新建beans.xml后頂部有一行提示,”Application context not configured for this file“,點擊提示最右方”Configure application context "即可,以下三步??



1、使用無參構造創建物件,默認!
2、使用有參構造創建物件,
-
通過下標賦值
<!-- 使用下標來構造有參物件--> <bean id="user" > <constructor-arg index="0" value="https://www.cnblogs.com/jdpromptly/p/李豐平"/> </bean>測驗結果如下??

-
通過引數的型別匹配
基本型別如int可以直接用,參考型別如string,必須用以下方式
<!-- 通過引數型別類匹配有參物件--> <bean id="user" > <constructor-arg type="java.lang.String" value="https://www.cnblogs.com/jdpromptly/p/李豐平"/> </bean>但如果兩種或者以上引數都是String,容易混亂,也不建議使用,
測驗結果如下??

-
直接通過引數名來設定
<!-- 通過引數名來配置--> <bean id="user" > <constructor-arg name="name" value="https://www.cnblogs.com/jdpromptly/p/李豐平"/> </bean>測驗結果如下??

測驗一個好玩的:
一個無參的其他類——創建一個兄弟物件,在beans.xml檔案中注冊,再到測驗檔案中測驗,結果是無論是否用該物件,該物件都會自動創建,且同一次只能有一個實體物件被創建,
流程??
新建UserTwo??
package com.kuang.pojo;
public class UserTwo {
private String name;
public UserTwo() {
System.out.println("UserTwo 被創建了,");
}
public UserTwo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
寫入bean.xml??
<bean id="usertwo" >
</bean>
在測驗案例中測驗??
import com.kuang.pojo.User;
import com.kuang.pojo.UserTwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 在getBean時,物件已經被創建,
User user = (User) context.getBean("user");
User user2 = (User) context.getBean("user");
user.show();
System.out.println(user == user2);
}
}
測驗結果??

總結:在組態檔加載時,容器中所管理物件已經初始化,
Spring配置
Alias別名
無論是之前的,還是起的別名,在getBean時都可以使用,
將??下面的代碼放入Beans.xml中
<!-- 如果添加了別名,我們也可以使用別名獲取到該物件-->
<alias name="user" alias="USER"/>
測驗檔案中下面兩種獲取物件方式等同??
import com.kuang.pojo.User;
import com.kuang.pojo.UserTwo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
// 在getBean時,物件已經被創建,
User user = (User) context.getBean("user");
User user2 = (User) context.getBean("USER");
user.show();
System.out.println(user == user2);
}
}
執行結果??

Bean配置
<!--id : bean 的唯一識別符號,也就是相當于我們學過的物件名
class : bean物件所對應的全限定名(包名+類名);必須這么寫
name : 也是別名,而且name可以同時取多個別名,可以通過空格分割,也可以通過“,”或者“;”分割
-->
<bean id="usertwo" name="usert ut,u2;utwo">
<constructor-arg name="name" value="https://www.cnblogs.com/jdpromptly/p/李豐平的別名"/>
</bean>
import匯入
一般用于團隊開發,該配置標簽可以將多個組態檔匯入合并為一個,
假設專案中有多個人開發,ABC,三人分別負責不同的類開發,不同的類需要注冊在不同的bean中,此時就可以利用import標簽,將所有人的bean.xml檔案合并成一個bean.xml檔案,使用時使用一個總的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">
<!--匯入之后,相當于三者檔案合并,可以直接通過本檔案獲取所有組態檔中的內容,-->
<import resource="beans.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
</beans>
依賴注入
構造器注入
Set方式注入【重點】
- 依賴注入:Set注入
- 依賴(依賴什么)??bean物件的創建依賴于容器
- 注入(注入什么)??bean物件中的所有屬性由容器來注入
【環境搭建】
-
復雜型別
Address??
package com.kuang.pojo; public class Address { private String address; public Address(String address) { this.address = address; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } -
真實測驗物件Student
package com.kuang.pojo; 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 String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public String[] getBooks() { return books; } public void setBooks(String[] books) { this.books = books; } public List<String> getHobbys() { return hobbys; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } public Map<String, String> getCard() { return card; } public void setCard(Map<String, String> card) { this.card = card; } public Set<String> getGames() { return games; } public void setGames(Set<String> games) { this.games = games; } public String getWife() { return wife; } public void setWife(String wife) { this.wife = wife; } public Properties getInfo() { return info; } public void setInfo(Properties info) { this.info = info; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", address=" + address + ", books=" + Arrays.toString(books) + ", hobbys=" + hobbys + ", card=" + card + ", games=" + games + ", wife='" + wife + '\'' + ", info=" + info + '}'; } } -
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="address" > <constructor-arg name="address" value=""/> </bean> <!--第一種,普通值注入,value--> <bean id="student" > <property name="address" ref="address"/> <!--第一種,普通值注入,value--> <!-- <property name="name" value="https://www.cnblogs.com/jdpromptly/p/李豐平"/>--> <!-- 也可以用下面的--> <property name="name" > <value>李豐平</value> </property> </bean> </beans> -
測驗類
import com.kuang.pojo.Student; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Student student = (Student) context.getBean("student"); System.out.println(student.getName()); } }運行效果??

拓展方式注入
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/457587.html
標籤:Java
