推薦學java——spring第一課(java spring菜鳥教程)
Spring簡介
官網地址:https://spring.io/
我們所熟知的 SSM 框架之一就是 Spring ,在這之前我們已經學習了 MyBatis. 最后就是 SpringMVC,2022加油干,兄弟姐妹們up~~
先來一張官網的全局框架圖:
這里的Spring Boot 和 Spring Cloud 相信各位都聽過,后面我們也會學習,今天的主角是 Spring Framework 也就是我們平時所說的 Spring框架,后面本文都稱之為Spring .
Spring Framework官網地址:https://spring.io/projects/spring-framework
Spring Framework API文檔:https://docs.spring.io/spring-framework/docs/current/Javadoc-api/
再來看看 Spring Framework 的架構圖:
Spring 將它理解為一個容器,這個容器的功能是可以創建Java對象、給java對象賦值、控制對象的生命周期。這個過程就叫做反轉。而創建java對象、給java對象賦值、控制對象的生命周期這個過程叫做控制。這就是Spring的第一個核心內容 IoC (Inversion of Control的縮寫,意為 控制反轉),簡言之,就是把對象的控制者交給了Spring。
IoC是一個理論思想,自己能理解就可以,而它的技術實現方案叫:DI(Dependency injection 的縮寫,意為 依賴注入)。
另外一個核心內容是:AOP(面向切面編程)。我們在學習過程中始終把握這兩個核心,不要偏移重點。
第一個Spring項目
1、我這里為了和前面學習的MyBatis作區分,先新建EmptyProject 然后添加名為spring-01的 Module ,這樣每次新建module即可。
2、添加Spring依賴(在pom.xml中)
3、定義接口和實現類
接口:
public interface SomeService { void doSome(); }
實現類:
public class SomeServiceImpl implements SomeService { @Override public void doSome() { System.out.println("實現接口 SomeService"); } }
4、在resources 目錄下創建Spring配置文件beans.xml,作用是聲明java對象,通過
5、通過容器使用對象
String config = "beans.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(config); // 根據id 獲取對象 SomeService someService = (SomeService) applicationContext.getBean("someService"); someService.doSome();
Spring是通過對象的無參構造方法來創建對象的,Spring是一次全部映射beans.xml中配置的對象。Spring這種管理對象的方式本質是反射技術。拿到容器之后,我們就可以通過容器提供的方法來操作Java對象了。
前面我們自定義了一個實現接口的Java類,Spring是可以拿到該類并調用方法的,那么系統類呢?Spring是否也可以拿到,我們在beans.xml中添加下面這樣一個系統類,來測試結果。
測試代碼和上面的類似:
// 系統類 Date date = (Date) applicationContext.getBean("javaDate"); System.out.println(date);
結果當然是肯定的。那么我們自定義一個類,但沒有實現接口,是否可以呢?答案也是可以的。各位感興趣可以自己嘗試,這里不做演示了。
Spring給屬性賦值
DI分類:
set注入,也叫設值注入(推薦使用)
構造方法注入
基本類型屬性的set注入
語法很簡單:
學生類Student中只有兩個屬性,分別是name和age. 測試代碼如下:
@Test public void testSet_student() { String config = "ba01/applicationContext.xml"; ApplicationContext context = new ClassPathXmlApplicationContext(config); Student student = (Student) context.getBean("myStudent"); System.out.println(student); }
結果各位自行測試,能正確輸出我們在xml中的賦值即可,當然這是我們自定義的java對象,如果使用系統的類呢?大家可以自行嘗試我們前面提到的java.util.Date類。
對象類型set注入
我們再定義一個Java對象School,有屬性name和address,然后在Student類中增加該對象。看具體代碼:
在原來的基礎上增加了引用類型對象的賦值,與簡單類型不同的是,這里使用了ref這個標簽屬性,很明顯,這是引用的意思,也就是引用了下面這段代碼:
這個時候測試結果接口看到我們的賦值,測試代碼相同的,就不貼了。
構造方法注入
我們給Student添加構造方法如下:
public Student(String name, int age, School school) { this.name = name; this.age = age; this.school = school; }
接著是applicationContext.xml 中的代碼:
構造方法的形參可以自定義,沒有必要和類屬性保持一致,也可以通過構造方法的形參的索引來賦值(如果不寫name或者index,只給value賦值也是可以的,默認就是按照索引來的)。測試代碼和前面一樣的,能輸出我們賦值的結果即為正確。
引用類型自動注入
byName 按名稱注入。Java對象中引用類型的屬性名和Spring容器中bean的id名稱一樣,且數據類型也相同,這些bean能夠賦值給引用類型。
byType 按類型注入。java對象中引用類型的數據類型和Spring容器中bean的class值是同源關系,這些bean能夠賦值給引用類型。
看下第一種方式的核心代碼:
兩個注意點:增加了 autowire 屬性,按名稱注入就是byName;引用對象的注冊
看第二種方式前,我們先搞清楚什么是同源關系?
Java實體類中引用類型的數據類型和bean的class值是一樣的
Java實體類中引用類型的數據類型和bean的class值是父子類關系
Java實體類中引用類型的數據類型和bean的class值是接口和實現類的關系
這里以第一種為例,其他兩種,相信各位自己都可以搞定,看我們的xml中代碼:
區別就是這里的 autowire 屬性值需要是 byType ;第二點就是引用類型的 class (也就是這里id為my_school 的 class值)需要和Java對象中聲明的引用類型是同一個。
測試代碼都是相同的,各位自行驗證哈。
import的使用
前面我們都是例子比較簡單的情況下,寫一個 Spring 配置文件就完成了所有工作,但實際開發中遠不止這點業務,可能需要我們將業務按照模塊劃分,這就需要我們提供獨立的配置文件,在現有基礎上,我們將 Student 和 School 進行獨立的配置,然后保留主配置文件,看流程:
新建 spring-student.xml 和 spring-school.xml ,內容分別如下:
修改原來的配置文件 applicationContext.xml 如下:
這里其實還可以使用通配符,個人建議初學容易犯小錯誤,還是暫時都用全路徑,這樣比較清晰明了,錯誤容易排查,也容易理解。
測試代碼如下:
/** * 測試 import 引入bean配置 */ @Test public void testImport() { String config = "ba06/applicationContext.xml"; ApplicationContext context = new ClassPathXmlApplicationContext(config); com.javafirst.ba06.Student student = (com.javafirst.ba06.Student) context.getBean("myStudent"); System.out.println(student); }
測試代碼其實沒有變化,結果各位自行驗證。
要學習的注解:
@Component 注解Java對象類前,創建java對象,給java對象起id,不寫其 value 值的話,默認是類名小寫。
@Repository 放在 dao 接口的實現類上面,創建java對象,是持久層的,可以訪問數據庫。
@Service 放在業務層接口的實現類上面,創建業務層java對象,業務層對象有事務功能。
@Controller 放在控制器上面,創建控制器java對象,是視圖層,能把請求結果顯示給用戶。
@Value 簡單類型屬性賦值。
@Autowired 引用類型屬性賦值。
創建java對象如下:
@Component(value = "my_student") // 不指定value,默認是類名小寫 public class Student { private String name; private int age; @Override public String toString() { return "Student信息:{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
和之前的區別少了屬性對應的 setXXX() 和 getXXX() 方法。
applicationConext.xml 對應代碼如下:
這里和之前的變化是不再需要手動添加
測試代碼和之前沒什么區別:
@Test public void testComponent() { String config = "ba01/applicationContext.xml"; ApplicationContext context = new ClassPathXmlApplicationContext(config); // 注意這里的 my_student 就是注解 @Component 的 value 值 Student student = (Student) context.getBean("my_student"); System.out.println(student); }
結果大家自行驗證即可。
針對簡單類型的屬性賦值使用。
我們在上面的基礎上,給 Student 對象的兩個屬性賦值,代碼如下:
@Value(value = "司馬如意") private String name; @Value("26") // 當注解只使用一個屬性的時候 注解屬性名可省略 private int age;
這種在屬性上面加注解的方式推薦使用,此外,還可以在對應的 setXXX() 方法上加注解,比如下面這樣:
@Value("諸葛如意") public void setName(String name) { this.name = name; }
如果兩個同時加上,則會取后者的值。結果大家自行測試即可。
當然 @Value 注解還可以給屬性賦值來自于外部文件中的值,我們在 resources 目錄下新建 myconfig.properties,該文件中的內容如下:
my_name=南極賢文 my_age=55
對應的,加載該文件的操作需要我們再來學習一個標簽,在 applicationContext.xml 中添加如下代碼:
這個其實和前面學習 MyBatis 的時候類似,我們也同樣配置過加載屬性文件的標簽。接下來看java對象代碼的變化:
/** * 給屬性賦值 來自于外部文件中的值 */ @Value("${my_name}") private String name; @Value("${my_age}") private int age;
測試代碼沒有變化,各位自行嘗試哈。
引用類型屬性賦值
我們在現有代碼基礎上增加一個 School 對象,并在原來的 Student 中聲明 School 屬性,對于 School 本身屬性的賦值,就是簡單類型賦值操作,其實各位已經學會了,主要看下 Student 中如何給引用類型添加注解:
@Component(value = "my_student") public class Student { /** * 給屬性加注解 推薦使用這種方式 */ @Value(value = "上官婉兒") private String name; @Value("22") private int age; /** * @Autowired 支持 byName 和 byType(默認) * 注解位置可在屬性上面,也可在屬性的 set 方法上面,推薦使用前者 */ @Autowired private School school; /** * @Autowired byName 方式 * 這種方式要結合 @Qualifier(value = "對象的@Component注解的value值") 注解一起使用,但在數寫上無先后順序 * 這種方式如果把 @Qualifier 注解的 value 值寫錯了,程序會終止(因為 @Autowired 注解的 required 值默認是true) */ // @Autowired // @Qualifier(value = "my_school") // private School school; @Override public String toString() { return "Student信息:{" + "name='" + name + '\'' + ", age=" + age + ", school=" + school + '}'; } }
對應的 School 中代碼如下:
@Component("my_school") public class School { @Value("乾坤學院") private String name; @Value("長安城光華街西北角") private String address; @Override public String toString() { return "School信息:{" + "name='" + name + '\'' + ", address='" + address + '\'' + '}'; } }
結果各位自行測試哈,很簡單。
jdk1.8本身自帶的,如果使用高于1.8,那么需要手動添加依賴
該注解同樣支持 byName(默認) 和 byType 兩種賦值方式, 不同于 @Autowired 的是 該注解如果 byName 賦值失敗,會自動使用 byType 賦值.
我們看下核心的注解代碼:
/** * @Resource 注解是jdk1.8本身自帶的,如果使用高于1.8,那么需要手動添加依賴 *
* 該注解同樣支持 byName(默認) byType兩種賦值方式, * 不同于 @Autowired 的是 該注解如果 byName 賦值失敗,會自動使用 byType 賦值.
* 如果只想使用 byName 方式, * 那么只需要給 @Resource 注解的 name屬性值指定為對象類型的 @Component 注解的value值(此時value值沒有必要和聲明的引用對象名相同) */ @Resource private School school;
我們知道,byName 方式是通過 id 匹配的,所以我們 School 類的 @Conponent 注解的 value 值應改為 school . 結果各位自己測試,相信能看到這里,說明你已經很熟練了,哈哈~
總結
文本開頭也提到了,Spring 中最重要的兩個知識點 IoC 和 AOP ,本節主要學習了前者
通過學習MyBatis ,現在學 Spring 就相對輕松一些了,因為很多內容似乎是相同的,其實這個感覺也可以用于學習不同編程語言之間
注解開發方式現在流行起來了,所以相對要重點掌握,但也要看自己所處的“環境”。
Java Spring 容器
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。