Spring
Spring簡介
Spring 是一個開源的設計層面框架,它解決的是業務邏輯層和其他各層的松耦合問題,因此它將面向介面的編程思想貫穿整個系統應
特點:
- Spring 是一個開源免費的框架,容器;
- Spring 是一個輕量級的框架,非入侵式的;
- 控制反轉 IoC,面向切面編程 AOP;
- 對事務的支持,對框架的支持,
優點:
- 方便解耦,簡化開發
- AOP編程的支持
- 宣告式事務的支持
- 方便程式的測驗
- 方便集成各種優秀的框架
- 降低JavaEE API的使用難度
Spring的體系結構:
Spring入門
Spring的開發步驟示意圖:
Spring程式開發步驟
-
在maven匯入Spring開發的基本包坐標
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.6</version> </dependency> </dependencies>
-
撰寫Dao介面和實作類
-
創建Spring核心組態檔
-
在Spring組態檔中配置UserDaoImpl
-
使用Spring的API獲得Bean實體
public class UserDaoDemo { public static void main(String[] args) { // 引數為spring組態檔 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); //引數為組態檔中為該實作類配置的id UserDao userDao =(UserDao) app.getBean("userDao"); userDao.save(); } }
? 成功運行
之前運行提示:Error:java: 錯誤: 不支持發行版本 5,在pom.xml中添加該配置,11為我的java版本
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
Spring組態檔
Bean標簽
-
用于配置物件交由spring創建,默認情況下呼叫類的無參建構式,不是無參建構式不能創建成功
-
基本屬性:id:唯一標識
? class:全限定名稱
<bean id="userDao" ></bean>
-
范圍配置:scope:每次通過spring得到的bean實體物件是不同的實體物件或者是同一個(單例)
與此同時單例在就加載組態檔時就進入了無參構造,只要容器在物件一直存在;而多例在獲得bean實體物件是進入無參構造,只要物件在使用一直存在,長時間不用被回收
-
Bean生命周期配置:
-
init-method:指定類中的初始化方法名稱
指定該類中的save方法在初始化時呼叫,銷毀同理: <bean id="userDao" scope="prototype" init-method="save"></bean>
-
destroy-method:指定類中銷毀方法名稱
-
-
Bean實體化三種方式:
-
無參構造方法實體化:默認,見上
-
工廠靜態方法實體化:
StaticFactory是工廠,getUserDao是StaticFactory的方法 <bean id="userDao" factory-method="getUserDao"></bean>
package com.myspring.dao.impl; public class StaticFactory { public static UserDaoImpl getUserDao(){ return new UserDaoImpl(); } }
-
工廠實體方法實體化
<bean id="userDao" ></bean> 因為非static需要實體物件,所以創建 <bean id="factory" ></bean> 再講兩種聯系起來 <bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean>
package com.myspring.dao.impl; public class Factory { public UserDaoImpl getUserDao(){ return new UserDaoImpl(); } }
-
依賴注入
-
依賴注入是spring框架核心ioc的具體實作
-
在撰寫程式時,層與層(例如業務層呼叫持久層方法)之間的依賴關系可以通過呼叫sprin來維護,簡單來說就是讓框架把持久層物件傳入業務層,不用我們直接獲取
兩種方式:
-
set方法:我的理解是相當于通過spring呼叫它的set方法
//業務層中 public class UserServiceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void save(){ userDao.save(); } } //外部層: public class UserDaoDemo { public static void main(String[] args) { // 引數為spring組態檔 ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); //引數為組態檔中為該實作類配置的id UserService userService =(UserService) app.getBean("userService"); userService.save(); } } //dao層代碼和上面的一樣
spring組態檔中 <bean id="userDao" ></bean> <bean id="userService" > <!-- name引數是userService中set方法名字set后面的單詞首小寫,ref:表示引向的bean實體id--> <property name="userDao" ref="userDao"></property> </bean>
? 簡便方法:p命名空間方式(本質上還是set):
? 使用方法:修改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"
<!-- 添加這一句 -->
xmlns:p="http://www.springframework.org/schema/p">
<bean id="userDao" ></bean>
<!-- bean修改成這樣 -->
<bean id="userService" p:userDao-ref="userDao">
</bean>
</beans>
- 構造方法
? 同理把業務層的set方法創建改成有參方法創建
在spring組態檔中:
<bean id="userService" >
<!-- name:構造方法引數名字,ref:bean id-->
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
其他資料注入
當然,除了可以注入bean實體,還可以注入其他資料:
- 普通資料型別
- 參考資料型別
- 集合資料型別
本質還是set方法
<bean id="userService" >
<!-- 基本資料型別-->
<property name="age" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/1"></property>
<!-- 參考資料型別-->
<property name="name" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/lihua"></property>
<!-- list-->
<property name="friends">
<list>
<value>xiaoming</value>
<value>xiahu</value>
</list>
</property>
<!-- map-->
<property name="familyName">
<map>
<entry key="mother" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/lili">
</entry>
<entry key="father" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/ligang">
</entry>
</map>
</property>
<!-- props-->
<property name="properties">
<props>
<prop key="p1">aaa</prop>
<prop key="p2">bbb</prop>
</props>
</property>
</bean>
引入其他組態檔
當spring組態檔過大時,可以根據不同功能拆分成幾個組態檔
那么只需要在主檔案中引入拆分的組態檔:
<import resource="applicationContext.xml"></import>
Spring相關API
ApplicationContext:介面型別,代表參考背景關系,可以通過其實體獲得Spring容器中的Bean物件
其體系結構:
ApplicationContext的實作類
- ClassPathXmlApplicationContext:它是從類的根路徑下加載組態檔推薦使用(resources目錄下)檔案型別xml
- FileSystemXmlApplicationContext:磁盤任意路徑加載組態檔檔案型別xml
- AnnotationConfigApplicationContext:使用注解配置容器物件,需要此類來創建spring容器,它用來讀取注解
getBean()方法的使用
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
//通過bean實體的id得到
UserService userService =(UserService)
app.getBean("userService");
//通過class型別尋找得到
app.getBean(UserService.class);
Spring配置資料源
資料源(連接池)
資料源的作用
常見資料源:DBCP、C3P0、BoneCP、Druid等
創建資料源
資料源的開發步驟:
- 匯入資料源坐標和資料庫驅動坐標(資料源可以自己選擇匯入那個公司的)
<!-- mysql-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>'
<!-- 資料源一:c3p0-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- 資料源二:druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- junit:單元測驗框架,與資料源沒聯系單純方便之后測驗-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
-
創建資料源物件(c3p0),其他資料源的創建可以自行搜索
-
設定資料源的基本連接資料
-
使用資料源獲取連接資源和歸還資源
public class DataSourceTest { // 這就是junit的 @Test //測驗手動創建c3p0資料源 public void test1() throws PropertyVetoException, SQLException { // 創建資料源:這是c3p0的創建方法 ComboPooledDataSource dataSource=new ComboPooledDataSource(); // 配置基本引數:一資料庫驅動 dataSource.setDriverClass("com.mysql.jdbc.Driver"); // 資料庫url dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/school"); // 用戶名 dataSource.setUser("root"); // 密碼 dataSource.setPassword("123456"); // 獲取資源 Connection connection = dataSource.getConnection(); // 測驗connection是否為空 System.out.println(connection); connection.close(); } }
運行測驗結果:不為空所以成功
當然,為了降低耦合最好還是把資料庫相關資訊抽取出來為一個單獨的組態檔
改進之后:
public class DataSourceTest { // 這就是junit的 @Test //測驗手動創建c3p0資料源 public void test1() throws PropertyVetoException, SQLException { //讀取組態檔;引數是相對于resources目錄的路徑,且不需要寫properties后綴 ResourceBundle rb = ResourceBundle.getBundle("jdbc"); String driver = rb.getString("jdbc.driver"); String url = rb.getString("jdbc.url"); String username = rb.getString("jdbc.username"); String password = rb.getString("jdbc.password"); //創建資料源物件、設定連接引數 // 創建資料源:這是c3p0的創建方法 ComboPooledDataSource dataSource=new ComboPooledDataSource(); // 配置基本引數:一資料庫驅動 dataSource.setDriverClass(driver); // 資料庫url dataSource.setJdbcUrl(url); // 用戶名 dataSource.setUser(username); // 密碼 dataSource.setPassword(password); // 獲取資源 Connection connection = dataSource.getConnection(); // 測驗connection是否為空 System.out.println(connection); connection.close(); } }
Spring 配置資料源
剛才是通過new來創建資料源,現在我們將資料源的創建權交給Spring容器去完成
組態檔中:
<!-- 可以通過右鍵資料源物件copy reference獲得class路徑-->
<bean id="dataSource" >
<!-- 為dataSource配置屬性,name中是固定寫法,都是資料源自己的屬性-->
<property name="driverClass" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/jdbc:mysql://localhost:3306/school"></property>
<property name="user" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/root"></property>
<property name="password" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/123456"></property>
</bean>
外部類中:
@Test
//測驗手動創建c3p0資料源
public void test1() throws PropertyVetoException, SQLException {
ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
DataSource dataSource = app.getBean(DataSource.class);
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
如果要在spring組態檔中引入properties檔案
<!-- 加載外部properties檔案-->
<context:property-placeholder location="jdbc.properties"></context:property-placeholder>
<!-- 可以通過右鍵資料源物件copy reference獲得class路徑-->
<bean id="dataSource" >
<!-- 不用再單獨來個組態檔通過這樣的方式配置,name為資料源的屬性-->
<property name="driverClass" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/${jdbc.driver}"></property>
<property name="jdbcUrl" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/${jdbc.url}"></property>
<property name="user" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/${jdbc.username}"></property>
<property name="password" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/${jdbc.password}"></property>
</bean>
Spring的注解開發
Spring是輕代碼而重配置的框架,配置比較繁重,影響開發效率,所有注解開發是一種趨勢,注解代替xml組態檔可以簡化配置,提高開發效率
Spring原始注解
-
主要替代
配置 -
原始注解有:
注解 說明 @Component 使用在類上用于實體化Bean @Controller 使用在web層類上用于實體化Bean @Service 使用在service層類上用于實體化Bean @Repository 使用在dao層類上用于實體化Bean @Autowired 使用在欄位上用于根據型別依賴注入 @Qualifier 結合@Autowired一起使用用于根據名稱進行依賴注入 @Resource 相當于@Autowired+@Qualifier,按照名稱進行注入 @Value 注入普通屬性 @Scope 標注Bean的作用范圍 @PostConstruct 使用在方法上標注該方法是Bean的初始化方法 @PreDestroy 使用在方法上標注該方法是Bean的銷毀方法 下面例子配置和注解等同:
//<bean id="userDao" ></bean> @Component("userDao") public class UserDaoImpl implements UserDao{}
// 注入bean實體 <property name="userDao" ref="userDao"></property> //另外xml檔案配置的方式該屬性必須有set或者建構式,但是注解方法可以省略 @Autowired//按照資料型別從spring容器中進行匹配 @Qualifier("userDao")//按照id的值從容器中進行匹配的,但是此處結合 @Autowired和 @Qualifier一起使用 private UserDao userDao;
最后,我們需要再組態檔中配置組件掃描:以識別注解
<!--配置組件掃描:base-package掃描包下所有--> <context:component-scan base-package="com.myspring"></context:component-scan>
其他原始注解講解:
-
@Controller、@Service、@Repository這三者和@Component作用完全相同但是,分別表示web層,service層、dao層的bean實體
-
@Resource(name="userDao")就等于@Autowired+@Qualifier("userDao")
-
@value:
//<property name="age" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/12"></property> @Value("12") private int age; //這個東西需要在組態檔中已載入properties檔案,具體見上 @Value("${jdbc.driver}") private String name;
-
@Scope("singleton"),參考bean的scope屬性
-
@PostConstruct完全類似bean的init-method
-
@PreDestroy類似bean的destroy-method
-
新注解
除了原始注解外,我沒還需要其他注解來覆寫其他原始注解無法實作的功能,例如:
- 非自定義的bean
- 加載properties檔案配置
- 組件掃描
- 引入其他檔案
新注解包括:
注解 | 說明 |
---|---|
@Configuration | 用于指定當前類是一個Spring配置類,當創建容器時會從該類上加載注解 |
@ComponentScan | 用于指定 Spring 在初始化容器時要掃描的包,作用和在Spring的xml組態檔中的<context:component-scan base-package="com"/>一樣 |
@Bean | 使用在方法上,標注將該方法的回傳值存盤到 Spring 容器中 |
@PropertySource | 用于加載.properties 檔案中的配置 |
@Import | 用于匯入其他配置類 |
新注解詳解實體:
datasourceconfiguration配置類:
//加載properties組態檔
@PropertySource("classpath:jdbc.properties")
public class DataSourceConfiguration {
// 通過這種方法賦值
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean("dataSource")//spring會將當前方法的回傳值以指定名稱存盤到spring容器中,引數為id
public DataSource getDataSource() throws PropertyVetoException {
// 創建資料源:這是c3p0的創建方法
ComboPooledDataSource dataSource=new ComboPooledDataSource();
// 配置基本引數:一資料庫驅動
dataSource.setDriverClass(driver);
// 資料庫url
dataSource.setJdbcUrl(url);
// 用戶名
dataSource.setUser(username);
// 密碼
dataSource.setPassword(password);
return dataSource;
}
}
/*相當于xml組態檔中的:
<!-- <bean id="dataSource" >-->
<!-- <property name="driverClass" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/${jdbc.driver}"></property>-->
<!-- <property name="jdbcUrl" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/${jdbc.url}"></property>-->
<!-- <property name="user" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/${jdbc.username}"></property>-->
<!-- <property name="password" value="https://www.cnblogs.com/rainaftersummert/archive/2023/07/08/${jdbc.password}"></property>-->
<!-- </bean>-->
核心配置類:
//標志該類是Spring的核心配置
@Configuration
//掃描com下的所有,相當于<context:component-scan base-package="com.myspring"></context:component-scan>
@ComponentScan("com.myspring")
//匯入datasourceconfiguration配置類,該類專注于資料庫相關
@Import({DataSourceConfiguration.class})
public class SpringConfiguration {
}
外部類測驗方法中:
// 組態檔為類時加載,區別于xml
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class);
DataSource dataSource = app.getBean(DataSource.class);
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
運行成功,
Spring集成Junit
spring測驗還是比較麻煩,可以通過Junit來簡化
-
讓SpringJunit來復制spring容器的創建,但需要將組態檔的名稱告訴他:可以簡化這兩句
ApplicationContext app = new AnnotationConfigApplicationContext(SpringConfiguration.class); DataSource dataSource = app.getBean(DataSource.class);
-
將需要bean自己在測驗類中注入
集成Junit的步驟:
-
匯入spring集成Junit的坐標
junit的坐標
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
spring集成junit坐標:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.3.6</version> </dependency>
-
使用@Runwith注解替換原來的運行期
-
使用@ContextConfiguration指定組態檔或配置類
-
使用@Autowired注入需要測驗的物件
-
創建測驗方法進行測驗
//java測驗類中:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")//配置類引數寫(classes={xxx.class})
public class SpringJunitTest {
@Autowired
private UserService userService;
@Test
public void test(){
userService.save();
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556841.html
標籤:其他
上一篇:RabbitMQ基本配置
下一篇:返回列表