Spring 5框架
一、Spring概念
1、Spring是輕量級的JavaEE框架
2、Spring可以解決企業應用開發的復雜性
3、Spring有兩個核心部分:IOC和AOP
? 1)IOC:控制反轉,把創建物件程序交給Spring進行管理
? 2)AOP:面向切面,不修改源代碼進行功能增強
4、Spring特點
- 方便解耦,簡化開發
- AOP編程的支持
- 方便程式的測驗
- 方便集成各種優秀框架(方便整合其他框架)
- 方便進行事務操作
- 降低API開發難度
入門案例:
1.下載地址:https://repo.spring.io/ui/native/release/org/springframework/spring
2.打開idea,新建java專案(專案例子檔案:Java/Spring at main · DFshmily/Java (github.com))
3.匯入Spring5相關jar包


4.創建普通類,在這個類創建普通方法
public class User{
public void add(){
System.out.println("add......");
}
}
5.創建Spring組態檔,在組態檔創建物件
Spring組態檔使用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">
<!--配置User物件創建-->
<bean id="user" ></bean>
</beans>
6.進行代碼測驗撰寫
User.java
package com.spring;
public class User {
public void add(){
System.out.println("add......");
}
}
TestSpring.java
package com.spring.testdemo;
import com.spring.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring {
@Test
public void testAdd(){
//1.加載spring組態檔
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2.獲取配置創建的物件
User user = context.getBean("user",User.class);
System.out.println(user);
user.add();
}
}
運行結果:
com.spring.User@506ae4d4
add......
二、IOC框架
1.IOC底層原理
(1)什么是IOC
? 1)控制反轉,把物件創建和物件之間的呼叫程序,交給Spring進行管理
? 2)使用IOC目的:為了耦合度降低
? 3)做入門案例就是IOC實作
(2)原理
? 1)xml決議、工廠模式、反射
? 

IOC程序:
- 第一步xml組態檔,配置創建的物件
<bean id="user" ></bean>
-
有service類和dao類,創建工廠類
class UserFactory{ public static UserDao getDao(){ String classValue = https://www.cnblogs.com/DFshmily/p/class屬性值;//xml決議 Class clazz = Class.forName(classValue);//通過反射創建物件 return (UserDao)clazz.newInstance(); } }
2.IOC介面(BeanFactory)
(1)IOC思想基于IOC容器完成,IOC容器底層就是物件工廠
(2)Spring提供IOC容器實作兩種方式:(兩個介面)
? 1)BeanFactory:IOC容器基本實作方式,是Spring內部的使用介面,不提供開發人員進行使用
? 加載組態檔的時候不會創建物件,在獲取物件(使用)時才創建
? 2)ApplicationContext:BeanFactory介面的子介面,提供更多更強大的功能,一般由開發人員進行使用
? 加載組態檔時候就會把在組態檔的物件進行創建
(3)ApplicationContext介面實作類

3.IOC操作Bean管理(基于xml方式)
(1)什么是Bean管理
? 1)Spring創建物件
? 2)Spring注入屬性
(2)Bean管理操作有兩種方式
? 1)基于xml組態檔方式實作
? 2)基于注解方式實作
(3)基于xml方式創建物件
<!--配置User物件創建-->
<bean id="user" ></bean>
? 1)在spring組態檔中,使用bean標簽,標簽里面添加對應屬性,就可以實作物件創建
? 2)在bean標簽有很多屬性,介紹常用的屬性
id屬性:唯一標識
class屬性:類全路徑(包類路徑)
? 3)創建物件的時候,默認也是執行無參構造方法完成物件的創建
(4)基于xml方式注入屬性
? 1)DI:依賴注入,就是注入屬性
? ?第一種注入方式:使用set方法注入
package com.spring;
public class Book {
private String bname;
public void setBname(String bname) {
this.bname = bname;
}
}
xml:
<!--set方法注入屬性-->
<bean id="book" >
<!--使用property完成屬性注入
name:類里面屬性名稱
value:向屬性注入的值-->
<property name="bname" value="https://www.cnblogs.com/DFshmily/p/shmily"></property>
</bean>
Test:
public class TestSpring {
@Test
public void OrdersTest(){
//1.加載spring組態檔
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2.獲取配置創建的物件
Book book = context.getBean("book",Book.class);
System.out.println(book);
book.toString();
}
}
運行結果:
Book{bname='shmily'}
? ?第二種注入方式:使用有參構造進行注入:
? 1)創建類,定義屬性,創建屬性對應有參構造方法
private String oname;
private String address;
//有參構造
public Orders(String oname, String address) {
this.oname = oname;
this.address = address;
}
? 2)在Spring組態檔中進行配置
<!--有引數構造注入屬性-->
<bean id="orders" >
<constructor-arg name="oname" value="https://www.cnblogs.com/DFshmily/p/PC"></constructor-arg>
<constructor-arg name="address" value="https://www.cnblogs.com/DFshmily/p/china"></constructor-arg>
還有個索引注入 <constructor-arg index="0" value="https://www.cnblogs.com/DFshmily/p/china"></constructor-arg>,"0"是下標
</bean>
? Test:
public class TestSpring {
@Test
public void OrdersTest(){
//1.加載spring組態檔
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//2.獲取配置創建的物件
Orders orders = context.getBean("orders",Orders.class);
System.out.println(orders);
orders.toString();
}
}
運行結果:
Orders{oname='PC', address='china'}
?第三種:p名稱空間注入
? 1)使用p名稱空間注入,可以簡化基于xml配置方式
? ①添加p名稱空間在組態檔中:
xmlns:p="http://www.springframework.org/schema/p"
? ②進行屬性注入,在bean標簽里面進行操作
<bean id="book" p:bname="書"></bean>
4.IOC操作Bean管理(xml其他型別屬性)
? (1)字面量
? 1)null值
<!--null值-->
<property name="address">
<null/>
</property>
? 2)屬性值包含特殊符號
<!--屬性值包含特殊符號
1.把<>進行轉義
2.把帶特殊符號內容寫到CDATA
-->
<property name="address">
<value><![CDATA[<<南京>>]]</value>
</property>
(2)注入屬性--外部bean
? 1)創建兩個類service類和dao類
? 2)在service呼叫dao里面的方法
public class UserService {
public void add(){
System.out.println("service add......");
}
//原始方式:創建UserDao物件
/*UserDao userDao = new UserDaoImpl();
userDao.update();*/
//創建UserDao型別屬性,生成set方法
private UserDao userDao;
public void setUserDao(UserDaoImpl userDao) {
this.userDao = userDao;
}
}
? 3)在spring組態檔進行配置
<!-- 1.service和dao物件創建-->
<bean id="userService" >
<!--注入userDao物件
name屬性:類里面屬性名稱
ref屬性:創建userDao物件bean標簽id值
-->
<property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" ></bean>
@Test
public void testAdd(){
//1.加載spring組態檔
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
//2.獲取配置創建的物件
UserService userService = context.getBean("userService",UserService.class);
userService.add();
}
(3)注入屬性--內部bean和級聯賦值
? 1)一對多關系:部門和員工
? 一個部門有多個員工,一個員工屬于一個部門
? 部門是一,員工是多
? 2)在物體類之間表示表示一對多關系,員工表示所屬部門,使用物件型別屬性進行表示
//部門類
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
}
//員工類
public class Emp {
private String ename;
private String gender;
//員工屬于某一個部門,使用物件形式表示
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
public void setEname(String ename) {
this.ename = ename;
}
public void setGender(String gender) {
this.gender = gender;
}
}
? 3)在spring組態檔進行配置
<!--內部bean-->
<bean id="emp" >
<!--設定兩個普通屬性-->
<property name="ename" value="https://www.cnblogs.com/DFshmily/p/shmily"></property>
<property name="gender" value="https://www.cnblogs.com/DFshmily/p/男"></property>
<!--設定物件型別屬性-->
<property name="dept">
<bean id="dept" >
<property name="dname" value="https://www.cnblogs.com/DFshmily/p/部門"></property>
</bean>
</property>
</bean>
4)注入屬性--級聯賦值
- 第一種:
<!--級聯賦值-->
<bean id="emp" >
<!--設定兩個普通屬性-->
<property name="ename" value="https://www.cnblogs.com/DFshmily/p/shmily"></property>
<property name="gender" value="https://www.cnblogs.com/DFshmily/p/男"></property>
<!--級聯賦值-->
<property name="dept" ref="dept"></property>
</bean>
<bean id="dept" >
<property name="dname" value="https://www.cnblogs.com/DFshmily/p/部門"></property>
</bean>
- 第二種:
<!--級聯賦值-->
<bean id="emp" >
<!--設定兩個普通屬性-->
<property name="ename" value="https://www.cnblogs.com/DFshmily/p/shmily"></property>
<property name="gender" value="https://www.cnblogs.com/DFshmily/p/男"></property>
<!--級聯賦值,用dept.dname時要生成get方法-->
<property name="dept" ref="dept"></property>
<property name="dept.dname" value="https://www.cnblogs.com/DFshmily/p/部門"></property>
</bean>
<bean id="dept" >
<property name="dname" value="https://www.cnblogs.com/DFshmily/p/部門"></property>
</bean>
5.IOC操作Bean管理(xml注入集合屬性)
(1)注入陣列型別屬性
(2)注入List集合型別屬性
(3)注入Map集合型別屬性
? 1)創建類,定義陣列、list、map、set型別屬性,生成對應set方法
package com.spring;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Stu {
//1.陣列型別屬性
private String[] courses;
//2.List集合型別屬性
private List<String >list;
//3.Map集合型別屬性
private Map<String,String> maps;
//4.set集合型別屬性
private Set<String> sets;
public void setCourses(String[] courses) {
this.courses = courses;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
}
? 2)在spring組態檔配置
<!--集合型別屬性注入-->
<bean id="stu" >
<!--陣列型別屬性注入-->
<property name="courses">
<array>
<value>java課程</value>
<value>MySQL</value>
</array>
</property>
<!-- 或者:list屬性注入-->
<property name="list">
<list>
<value>D</value>
<value>F</value>
</list>
</property>
<!-- map型別屬性注入-->
<property name="maps">
<map>
<entry key="JAVA" value="https://www.cnblogs.com/DFshmily/p/java"></entry>
<entry key="C" value="https://www.cnblogs.com/DFshmily/p/c"></entry>
</map>
</property>
<!-- set型別屬性注入-->
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
Test:
package testdemo;
import com.spring.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class StuTest {
@Test
public void testCollection(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Stu stu = context.getBean("stu",Stu.class);
stu.test();
}
}
運行結果:
[java課程, MySQL]
[D, F]
{JAVA=java, C=c}
(4)在集合里面這種物件型別值
<!--創建多個course物件-->
<bean id="course1" >
<property name="cname" value="https://www.cnblogs.com/DFshmily/p/名字1"></property>
</bean>
<bean id="course2" >
<property name="cname" value="https://www.cnblogs.com/DFshmily/p/名字2"></property>
</bean>
<!-- 注入list集合型別,值是物件-->
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
</bean>
(5)把集合注入部分提取出來
? 1)在spring組態檔中參考名稱空間util
<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
</beans>
? 2)使用util標簽完成list集合注入
<!-- 1.提取list集合型別屬性注入-->
<util:list id="bookList">
<value>如何閱讀一本書</value>
<value>java</value>
<value>C</value>
</util:list>
<!-- 2.提取list集合型別屬性注入使用-->
<bean id="book" >
<property name="list" ref="bookList"></property>
</bean>
6.IOC操作Bean管理(FactoryBean)
(1)Spring有兩種型別bean:一種普通bean,另一種工廠bean(FactoryBean)
(2)普通bean:在組態檔中定義bean型別就是回傳型別
(3)工廠bean:在組態檔定義bean型別可以和回傳型別不一樣
? 1)第一步 創建類,讓這個類作為工廠bean,實習介面FactoryBean
? 2)第二步 實作介面里面的方法,在實作的方法中定義回傳的bean型別
MyBean.java
package com.factorybean;
import com.spring.Course;
import org.springframework.beans.factory.FactoryBean;
public class MyBean implements FactoryBean<Course> {
//定義回傳bean
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("dzq");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return false;
}
}
Test:
package testdemo;
import com.spring.Course;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class factorybeanTest {
@Test
public void testCollection1(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
}
組態檔:
<bean id="myBean" >
</bean>
7.IOC操作Bean管理(bean作用域)
(1)在Spring里面,設定創建bean實體時單實體還是多實體
(2)在Spring里面,默認情況下bean是單實體物件
@Test
public void testCollection2(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Book book1 = context.getBean("book",Book.class);
Book book2 = context.getBean("book",Book.class);
System.out.println(book1);
System.out.println(book2);
}
運行結果:
com.spring.Book@6cb107fd
com.spring.Book@6cb107fd
因為book1和book2的地址相同,所以他們是單實體物件
(3)如何設定單實體還是多實體
? 1)在spring組態檔bean標簽里面有屬性(scope)用于設定單實體還是多實體
? 2)scope屬性值
第一個值 默認值:singleton,表示單實體物件
第二個值 prototype,表示多實體物件
<bean id="book" scope="prototype">
<property name="list" ref="bookList"></property>
</bean>
運行結果:
com.spring.Book@710636b0
com.spring.Book@3de8f619
它們地址不同,現在是多實體物件
? 3)singleton和prototype區別
? 1.singleton單實體,prototype多實體
? 2.設定scope值是singleton時候,加載spring組態檔的時候就會創建單實體物件
? 設定scope值是prototype時候,不是在加載spring組態檔時候創建物件,在呼叫getBean方法時候創建多實體物件
? 了解:request:每一次HTTP請求都會創建一個新的bean實體,該bean僅在當前HTTP request內有效,在請求完成后,bean會失效并被垃圾回收器回收,
? session:每一次HTTP請求都會創建一個新的bean,該bean僅在當前HTTP session內有效,同一個session會話共享一個實體,不同的會話使用不同的實體,
8.IOC操作Bean管理(bena生命周期)
(1)生命周期
? 1)從物件創建到物件銷毀的程序
(2)bean生命周期
? 1)通過構造器創建bean實體(無引數構造)
? 2)為bean的屬性設定值和對其他bean參考(呼叫set方法)
? 3)呼叫bean的初始化的方法(需要進行配置初始化的方法)
? 4)bean可以使用了(物件獲取到了)
? 5)當容器關閉時候,呼叫bean的銷毀的方法(需要進行配置銷毀的方法)
(3)演示bean的生命周期
例子:
package com.bean;
public class Orders {
private String oname;
@Override
public String toString() {
return "Orders{" +
"oname='" + oname + '\'' +
'}';
}
//1.無參構造
public Orders() {
System.out.println("第一步 執行無引數構造創建bean實體");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 呼叫set方法設定屬性值");
}
//創建執行的初始化的方法
private void initMethod(){
System.out.println("第三步 執行初始化的方法");
}
//創建執行的銷毀的方法
public void destroyMethod(){
System.out.println("第五步 執行銷毀的方法");
}
}
組態檔:
<bean id="orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="https://www.cnblogs.com/DFshmily/p/手機"></property>
</bean>
Test:
public class OrdersTest {
@Test
public void orderTset(){
// ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步 獲取創建bean實體物件");
System.out.println(orders);
//手動讓bean實體銷毀
context.close();
}
運行結果:
第一步 執行無引數構造創建bean實體
第二步 呼叫set方法設定屬性值
第三步 執行初始化的方法
第四步 獲取創建bean實體物件
Orders{oname='手機'}
第五步 執行銷毀的方法
(4)bean的后置處理器,bean的生命周期有七步
? 1)通過構造器創建bean實體(無引數構造)
? 2)為bean的屬性設定值和對其他bean參考(呼叫set方法)
? 3)把bean實體傳遞給bean后置處理器的方法postProcessBeforeInitialization
? 4)呼叫bean的初始化的方法(需要進行配置初始化的方法)
? 5)把bean實體傳遞給bean后置處理器的方法postProcessAfterInitialization
? 6)bean可以使用了(物件獲取到了)
? 7)當容器關閉時候,呼叫bean的銷毀的方法(需要進行配置銷毀的方法)
(5)演示添加后置處理器的效果
? 1)創建類、實作介面BeanPostProcessor,創建后置處理器
MyBeanPost.java
package com.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第三步 在初始化之前執行的方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步 在初始化之后執行的方法");
return bean;
}
}
Orders.java
package com.bean;
public class Orders {
private String oname;
@Override
public String toString() {
return "Orders{" +
"oname='" + oname + '\'' +
'}';
}
//1.無參構造
public Orders() {
System.out.println("第一步 執行無引數構造創建bean實體");
}
public void setOname(String oname) {
this.oname = oname;
System.out.println("第二步 呼叫set方法設定屬性值");
}
//創建執行的初始化的方法
private void initMethod(){
System.out.println("第四步 執行初始化的方法");
}
//創建執行的銷毀的方法
public void destroyMethod(){
System.out.println("第七步 執行銷毀的方法");
}
}
組態檔:
<bean id="orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="https://www.cnblogs.com/DFshmily/p/手機"></property>
</bean>
<!-- 配置后置處理器-->
<bean id="myBeanPost" ></bean>
Test:
package testdemo;
import com.bean.Orders;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class OrdersTest {
@Test
public void orderTset(){
// ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第六步 獲取創建bean實體物件");
System.out.println(orders);
//手動讓bean實體銷毀
context.close();
}
}
運行結果
第一步 執行無引數構造創建bean實體
第二步 呼叫set方法設定屬性值
第三步 在初始化之前執行的方法
第四步 執行初始化的方法
第五步 在初始化之后執行的方法
第六步 獲取創建bean實體物件
Orders{oname='手機'}
第七步 執行銷毀的方法
9.IOC操作Bean管理(xml自動裝配)
(1)什么是自動裝配
? 1)根據指定裝配規則(屬性名稱或者屬性型別),Spring自動匹配屬性值進行注入
(2)演示自動裝配程序
? 1)根據屬性名稱自動注入
配置:
<!--手動裝配-->
<!-- <bean id="emp" >-->
<!-- <property name="dept" ref="dept"></property>-->
<!-- </bean>-->
<!-- <bean id="dept" ></bean>-->
<!-- 實作自動裝配
bean標簽屬性autowire,配置自動裝配
autowire屬性常用兩個值:
byName根據屬性名稱注入,注入值bean的id值和類屬性名稱一樣
byType根據屬性型別注入
-->
<bean id="emp" autowire="byName">
</bean>
<bean id="dept" ></bean>
Emp.java
package com.autowire;
//員工
public class Emp {
private Dept dept;
public void setDept(Dept dept) {
this.dept = dept;
}
@Override
public String toString() {
return "Emp{" +
"dept=" + dept +
'}';
}
public void test(){
System.out.println(dept);
}
}
Dept.java
package com.autowire;
//部門
public class Dept {
@Override
public String toString() {
return "Dept{}";
}
}
Test:
public class TestSpring {
@Test
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
Emp emp = context.getBean("emp",Emp.class);
System.out.println(emp);
}
}
運行結果:
Emp{dept=Dept{}}
? 2)根據屬性型別自動注入
<bean id="emp" autowire="byType">
</bean>
<bean id="dept" ></bean>
10.IOC操作Bean管理(外部屬性檔案)
(1)直接配置資料庫資訊
? 1)配置Druid(德魯伊)連接池
? 2)引入Druid連接池jar包(下載地址:[Central Repository: com/alibaba/druid (maven.org)](https://druid.apache.org/downloads.html))
? 組態檔:
<!-- 直接配置連接池-->
<bean id="dataSource" >
<property name="driverClassName" value="https://www.cnblogs.com/DFshmily/p/com.mysql.jdbc.Driver"></property>
<property name="url" value="https://www.cnblogs.com/DFshmily/p/jdbc:mysql://localhost:3306/book"></property>
<property name="username" value="https://www.cnblogs.com/DFshmily/p/root"></property>
<property name="password" value=""></property>
</bean>
(2)引入外部屬性檔案配置資料庫連接池
? 1)創建外部屬性檔案,properties格式檔案,寫資料庫資訊
prop.driverClass=com.mysql.jdbc.Driver
prop.url=jdbc:mysql://localhost:3306/book
prop.username=root
prop.password=""
? 2)把外部properties屬性檔案引入到spring組態檔中
? ?引入context命名空間
<?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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
? ?在spring組態檔使用標簽引入外部屬性檔案
<!-- 引入外部屬性檔案-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置連接池-->
<bean id="dataSource" >
<property name="driverClassName" value="https://www.cnblogs.com/DFshmily/p/${prop.driverClass}"></property>
<property name="url" value="https://www.cnblogs.com/DFshmily/p/${prop.url}"></property>
<property name="username" value="https://www.cnblogs.com/DFshmily/p/${prop.username}"></property>
<property name="password" value="https://www.cnblogs.com/DFshmily/p/${prop.password}"></property>
</bean>
11.IOC操作Bean管理(基于注解方式)
(1)什么是注解
? 1)注解是代碼特殊標記,格式:@注解名稱(屬性名稱=屬性值,屬性名稱=屬性值...)
? 2)使用注解,注解可以作用在類、方法、屬性上面
? 3)使用注解目的:簡化xml配置
(2)Spring針對Bean管理創建物件提供注解
? 1)@Component
? 2)@Service
? 3)@Controller
? 4)@Repository
? 上面四種注解功能是一樣的,都可以用來創建bean實體
(3)基于注解方式實作物件創建
? 1)引入依賴:spring-aop-5.3.9.jar
? 2)開啟組件掃描
<!-- 開啟組件掃描
如果掃描多個包,多個包用逗號隔開或者掃描包上層目錄
-->
<context:component-scan base-package="com"></context:component-scan>
? 3)創建類,在類上面添加物件注解
package com.service;
import org.springframework.stereotype.Component;
/*
在注解里面value屬性值可以省略不寫
默認值是類名稱,首字母小寫
UserService-->userService
@Component可以替代為@Service,@Controller,@Repository,但在此一般習慣于用@Component
*/
@Component(value = "https://www.cnblogs.com/DFshmily/p/userService")//<bean id="userService" />
public class UserService {
public void add(){
System.out.println("service add...");
}
}
(4)開啟組件掃描細節配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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.xsd
http://www.springframework.org/schema/p http://www.springframework.org/schema/p/spring-p.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 開啟組件掃描
如果掃描多個包,多個包用逗號隔開或者掃描包上層目錄
-->
<context:component-scan base-package="com"></context:component-scan>
<!-- 實體1:use-default-filters="false" 表示現在不使用默認filter,自己配置filter
context:include-filter 表示掃描哪些內容
-->
<context:component-scan base-package="com" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 實體2:
下面配置掃描包所有內容
context:exclude-filter 設定哪些內容不進行掃描
-->
<context:component-scan base-package="com">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
(5)基于注解方式實作屬性注入
? 1)@AutoWired :根據屬性型別進行自動裝配
? ①把service和dao物件創建,在service和dao類添加創建物件
? ②在service注入dao物件,在service類添加dao型別dao型別屬性,在屬性上面使用注解
UserService.java
package com.service;
import com.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
//定義dao型別屬性,不需要添加set方法,添加注入屬性注解
@Autowired //根據型別進行注入
private UserDao userDao;
public void add(){
System.out.println("service add...");
userDao.add();
}
}
UserDao.java
package com.dao;
public interface UserDao {
public void add();
}
UserDaoImpl.java
package com.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{
@Override
public void add(){
System.out.println("dao add...");
}
}
Test:
@Test
public void userTest(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean7.xml");
UserService userService=context.getBean("userService", UserService.class);
userService.add();
}
}
運行結果;
service add...
dao add...
? 2)@Qualifier:根據屬性名稱進行注入
? @Qualifier注解的使用,和@AutoWired一起使用
UserService.java
@Service
public class UserService {
//定義dao型別屬性,不需要添加set方法,添加注入屬性注解
@Autowired //根據型別進行注入
@Qualifier(value = "https://www.cnblogs.com/DFshmily/p/userDaoImpl1") //根據名稱進行注入
private UserDao userDao;
public void add(){
System.out.println("service add...");
userDao.add();
}
}
UserDaoImpl.java
@Repository(value = "https://www.cnblogs.com/DFshmily/p/userDaoImpl1")
public class UserDaoImpl implements UserDao{
@Override
public void add(){
System.out.println("dao add...");
}
}
? 3)@Resource:可以根據型別注入,也可以根據名稱注入
@Service
public class UserService {
//@Resource() //根據型別進行注入
@Resource(name = "userDaoImpl1") //根據名稱進行注入
private UserDao userDao;
public void add(){
System.out.println("service add...");
userDao.add();
}
}
? 4)@Value:注入普通型別屬性
@Value(value = "https://www.cnblogs.com/DFshmily/p/DF")
private String name;
(6)完全注解開發
? 1)創建配置類,替代xml組態檔
SpringConfig.java
package com.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //作為配置類,替代xml組態檔
@ComponentScan(basePackages = {"com"})
public class SpringConfig {
}
? 2)撰寫測驗類
package com.testdemo;
import com.config.SpringConfig;
import com.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class TestSpring {
@Test
public void userTest(){
//加載配置類
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
UserService userService=context.getBean("userService", UserService.class);
userService.add();
}
}
三、AOP
1.概念
(1)什么是AOP
? 1)面向切面編程(方面),利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率,
? 2)通俗描述:不通用修改源代碼方式,在主干功能里添加新功能
? 3)使用登錄例子說明AOP

### 2.AOP(底層原理)
(1)AOP底層使用動態代理
? 1)有兩種情況動態代理
? ①有介面情況,使用JDK動態代理
? ?創建介面實作類代理物件,增強類的方法

? ②沒有介面情況,使用CGLTB動態代理
? ?創建子類的代理物件,增強類的方法

3.AOP(JDK動態代理)
(1)使用JDK動態代理,使用proxy類里面的方法創建代理物件
java.lang.reflect
Class Proxy
java.lang.Object
java.lang.reflect.Proxy
? 1)呼叫newProxyInstance方法
static Object newProxyInstance(ClassLoader loader, 類<?>[] interfaces, InvocationHandler h)
回傳指定的介面,將方法呼叫指定的呼叫處理程式的代理類的一個實體,
? 方法中的三個引數:
| ClassLoader loader | 類加載器 |
|---|---|
| 類<?>[] interfaces | 增強方法所在的類,這個類實作的介面,支持多個介面 |
| InvocationHandler h | 實作這個介面InvocationHandler,創建代理物件,寫增強的方法 |
(2)撰寫JDK動態代碼
? 1)創建介面,定義方法
UserDao.java
package com.spring;
public interface UserDao {
public int add(int a,int b);
public String update(String id);
}
? 2)創建介面實作類,實作方法
UserDaoImpl.java
package com.spring;
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String update(String id) {
return id;
}
}
? 3)使用Proxy類創建介面代理物件
JDKProxy.java
package com.spring;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
public class JDKProxy {
public static void main(String[] args) {
//第一種:創建介面實作類代理物件
Class[] interfaces = {UserDao.class};
// Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// });
//第二種:自定義名稱UserDaoProxy創建代理物件代碼
UserDaoImpl userDao = new UserDaoImpl();
UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
int result = dao.add(1,2);
System.out.println("result:"+result);
}
}
//第二種:自定義名稱UserDaoProxy創建代理物件代碼
class UserDaoProxy implements InvocationHandler{
/*
1.把創建的是誰的代理物件,把誰傳遞過來
有參構造傳遞
*/
private Object obj;
public UserDaoProxy(Object obj){
this.obj = obj;
}
//增強的邏輯
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法之前
System.out.println("在方法之前執行..."+method.getName()+":傳遞的引數:"+ Arrays.toString(args));
//被增強的方法執行
Object res = method.invoke(obj, args);
//方法之后
System.out.println("在方法之后執行..."+obj);
return res;
}
}
運行結果:
在方法之前執行...add:傳遞的引數:[1, 2]
add方法執行了...
在方法之后執行...com.spring.UserDaoImpl@7ca48474
result:3
4.AOP(術語)
(1)連接點
? 類里面哪些方法可以被增強,這些方法稱為連接點
(2)切入點
? 實際被真正增強的方法,稱為切入點
(3)通知(增強)
? 1)實際增強的邏輯部分稱為通知(增強)
? 2)通知有多種型別
? ①前置通知
? ②后置通知
? ③環繞通知
? ④例外通知
? ⑤最終通知 finally
(4)切面
? 是動作,把通知應用到切入點的程序
5.AOP(準備)
(1)Spring框架一般基于AspectJ實作AOP操作
? 1)什么是AspectJ
AspectJ不是Spring組成部分,獨立AOP框架,一般把AspectJ和Spring框架一起使用,進行AOP操作
(2)基于AspectJ實作AOP操作
? 1)基于xml組態檔
? 2)基于注解方式實作(使用)
(3)在專案工程里面引入AOP相關依賴

(4)切入點運算式
? 1)切入點運算式的作用:知道對哪個類里面的哪個方法進行增強
? 2)語法結構:
? execution([權限修飾符] [回傳型別] [類全路徑] [方法名稱] [引數串列])
舉例1:對com.spring.UserDao類里面的add進行增強
? execution(* com.spring.UserDao.add(...))
舉例2:對com.spring.UserDao類里面的所有方法進行增強
? execution(* com.spring.UserDao.*(...))
舉例3:對com.spring包里面所有類,類里面的所有方法進行增強
? execution(* com.spring.*.*(...))
6.AOP操作(AspectJ注解)
(1)創建類,在類里面定義方法
User.java
package com.aop;
public class User {
public void add(){
System.out.println("add...");
}
}
(2)創建增強類(撰寫增強邏輯)
(1)在增強類中創建方法,讓不同方法代表不同通知型別
UserProxy.java
package com.aop;
//增強的類
public class UserProxy {
//前置通知
public void before(){
System.out.println("before...");
}
}
(3)進行通知的配置
? 1)在spring組態檔中,開啟注解掃描
<?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"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd ">
<!-- 開啟注解掃描-->
<context:component-scan base-package="com.aop"></context:component-scan>
</beans>
? 2)使用注解創建User和UserProxy物件
User.java
//被增強的類
@Component
public class User {
public void add(){
System.out.println("add...");
}
}
UserProxy.java
//增強的類
@Component
public class UserProxy {
//前置通知
public void before(){
System.out.println("before...");
}
}
? 3)在增強類上面添加注解@Aspect
UserProxy.java
//增強的類
@Component
@Aspect //生成代理物件
public class UserProxy {
//前置通知
public void before(){
System.out.println("before...");
}
}
? 4)在spring組態檔中開啟生成代理物件
xml:
<!-- 開啟aspect生成代理物件-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
(4)配置不同型別的通知
? 1)在增強類的里面,在作為通知方法上面添加通知型別注解,使用切入點運算式配置
UserProxy.java
package com.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
//增強的類
@Component
@Aspect //生成代理物件
public class UserProxy {
//前置通知
//@Before注解表示作為前置通知
@Before(value = "https://www.cnblogs.com/DFshmily/p/execution(* com.aop.User.add(..))")
public void before(){
System.out.println("before...");
}
//最終通知
@After(value = "https://www.cnblogs.com/DFshmily/p/execution(* com.aop.User.add(..))")
public void after(){
System.out.println("after...");
}
//后置通知(回傳通知)
@AfterReturning(value = "https://www.cnblogs.com/DFshmily/p/execution(* com.aop.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning...");
}
//例外通知
@AfterThrowing (value = "https://www.cnblogs.com/DFshmily/p/execution(* com.aop.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing...");
}
//環繞通知
@Around(value = "https://www.cnblogs.com/DFshmily/p/execution(* com.aop.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("環繞之前...");
//被增強的方法執行
proceedingJoinPoint.proceed();
System.out.println("環繞之后...");
}
}
Test:
package com.testdemo;
import com.aop.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {
@Test
public void testAop(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user = context.getBean("user", User.class);
user.add();
}
}
運行結果:
環繞之前...
before...
add...
afterReturning...
after...
環繞之后...
(5)相同的切入點抽取
//相同切入點抽取
@Pointcut(value = "https://www.cnblogs.com/DFshmily/p/execution(* com.aop.User.add(..))")
public void pointcut(){
}
//前置通知
//@Before注解表示作為前置通知
@Before(value = "https://www.cnblogs.com/DFshmily/p/pointcut")
public void before(){
System.out.println("before...");
}
(6)有多個增強類多個同一方法進行增強,設定增強類優先級
? 1)在增強類上面添加注解@Order(數字型別值),數字型別值越小優先級越高
@Component
@Aspect
@Order(1)
public class PersonProxy {
@Before(value = "https://www.cnblogs.com/DFshmily/p/execution(* com.aop.User.add(..))")
public void afterReturning(){
System.out.println("Person Before...");
}
}
(7)完全使用注解開發
? 1)創建配置類,不需要創建xml組態檔
@Configuration
@ComponentScan(basePackages ="com.aop" )
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
7.AOP操作(AspectJ組態檔)
(1)創建兩個類,增強類和被增強類,創建方法
Book.java
package com.aopxml;
//被增強類
public class Book {
public void buy(){
System.out.println("buy...");
}
}
BookProxy.java
package com.aopxml;
//增強類
public class BookProxy {
public void before(){
System.out.println("before...");
}
}
(2)在spring組態檔中創建兩個類物件
<?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="book" ></bean>
<bean id="bookProxy" ></bean>
</beans>
(3)在spring組態檔中配置切入點
<!-- 配置aop增強-->
<aopa:config>
<!-- 切入點-->
<aopa:pointcut id="point" expression="execution(* com.aopxml.Book.buy(..))"/>
<!-- 配置切面-->
<aopa:aspect ref="bookProxy">
<!-- 配置增強作用在具體的方法上-->
<aopa:before method="before" pointcut-ref="point"/>
</aopa:aspect>
</aopa:config>
Test:
@Test
public void testAop1(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
book.buy();
}
運行結果:
before...
buy...
四、JdbcTemplate
1.什么是JdbcTemplate
(1)Spring框架對JDBC進行封裝,使用JdbcTemplate方便實作對資料庫操作
2.準備作業
(1)引入相關jar包

(2)在spring組態檔中配置資料庫連接池
<!-- 資料庫連接池-->
<bean id="dataSource" destroy-method="close">
<property name="url" value="https://www.cnblogs.com/DFshmily/p/jdbc:mysql://localhost:3306/book"></property>
<property name="username" value="https://www.cnblogs.com/DFshmily/p/root"></property>
<property name="password" value=""></property>
<property name="driverClassName" value="https://www.cnblogs.com/DFshmily/p/com.mysql.jdbc.Driver"></property>
</bean>
(3)配置JdbcTemplate物件,注入DataSource
<!-- JdbcTemplate物件-->
<bean id="jdbcTemplate" >
<!-- 注入dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
(4)創建sercvice類,創建dao類,在dao注入jdbcTemplate物件
? ?組態檔
<!-- 開啟組件掃描-->
<context:component-scan base-package="com"></context:component-scan>
? ?service
package com.service;
import com.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookService {
//注入dao
@Autowired
private BookDao bookDao;
}
?Dao
package com.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
}
3.JdbcTemplate操作資料庫(添加)
(1)對應資料庫表創建物體類
User.java
package com.entity;
public class User {
private Integer id;
private String username;
private String password;
private String email;
public Integer getId() {
return id;
}
public String getUsername() {
return username;
}
public void setId(Integer id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public String getEmail() {
return email;
}
}
(2)撰寫service和dao
? 1)在dao進行資料庫添加操作
? 2)呼叫JdbcTemplate物件里面update方法實作添加操作
update(String sql,Object...args)
有兩個引數:
?第一個引數:sql陳述句
?第二個引數:可變引數,設定sql陳述句值
BookDaoImpl.java
package com.dao;
import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
//添加的方法
@Override
public void add(Book book) {
//1.創建sql陳述句
String sql = "insert into t_user values(?,?,?)";
//2.呼叫方法實作
int update = jdbcTemplate.update(sql,book.getId(),book.getUsername(),book.getPassword(),book.getEmail());
System.out.println(update);
}
}
BookService.java
package com.service;
import com.dao.BookDao;
import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookService {
//注入dao
@Autowired
private BookDao bookDao;
//添加的方法
public void addBook(Book book){
bookDao.add(book);
}
}
BookDao.java
package com.dao;
import com.entity.Book;
public interface BookDao {
//添加的方法
void add(Book book);
}
Book.java
package com.entity;
public class Book {
private String id;
private String username;
private String password;
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public String getEmail() {
return email;
}
}
(3)測驗類
package com.test;
import com.entity.Book;
import com.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TsetBook {
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",BookService.class);
Book book = new Book();
book.setId("7");
book.setUsername("c");
book.setPassword("c");
book.setEmail("[email protected]");
bookService.addBook(book);
}
}
運行結果:
10月 02, 2022 7:44:51 下午 com.alibaba.druid.pool.DruidDataSource info
資訊: {dataSource-1} inited
1
4.JdbcTemplate操作資料庫(修改和洗掉)
BookService.java
package com.service;
import com.dao.BookDao;
import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookService {
//注入dao
@Autowired
private BookDao bookDao;
//添加的方法
public void addBook(Book book){
bookDao.add(book);
}
//修改的方法
public void updateBook(Book book){
bookDao.update(book);
}
//洗掉的方法
public void deleteBook(String id){
bookDao.delete(id);
}
}
BookDao.java
package com.dao;
import com.entity.Book;
public interface BookDao {
//添加的方法
void add(Book book);
void update(Book book);
void delete(String id);
}
BookDaoImpl.java
package com.dao;
import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
//添加的方法
@Override
public void add(Book book) {
//1.創建sql陳述句
String sql = "insert into t_user values(?,?,?,?)";
//2.呼叫方法實作
int update = jdbcTemplate.update(sql,book.getId(),book.getUsername(),book.getPassword(),book.getEmail());
System.out.println(update);
}
//修改
@Override
public void update(Book book) {
String sql = "update t_user set username=?,password=?,email=?,where id=?";
Object[] args = {book.getUsername(),book.getPassword(), book.getEmail(),book.getId()};
int update = jdbcTemplate.update(sql,args);
System.out.println(update);
}
//洗掉
@Override
public void delete(String id) {
String sql = "delete from t_user where id=?";
int update = jdbcTemplate.update(sql,id);
System.out.println(update);
}
}
Test:
package com.test;
import com.entity.Book;
import com.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TsetBook {
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",BookService.class);
//添加
// Book book = new Book();
// book.setId("7");
// book.setUsername("c");
// book.setPassword("c");
// book.setEmail("[email protected]");
// bookService.addBook(book);
//修改
// Book book = new Book();
// book.setId("7");
// book.setUsername("python");
// book.setPassword("p");
// book.setEmail("[email protected]");
// bookService.updateBook(book);
//
//洗掉
bookService.deleteBook("7");
}
}
運行結果:
資訊: {dataSource-1} inited
1
5.JdbcTempalte操作資料庫(查詢回傳某個值)
(1)查詢表里面有多少條記錄,回傳是某個值
(2)使用JdbcTemplate實作查詢回傳某個值代碼
queryForObject(String sql,Class<T> requiredType)
有兩個引數:
?第一個引數:sql陳述句
?第二個引數:回傳型別Class
BookDaoImpl.java
package com.dao;
import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BookDaoImpl implements BookDao{
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
//添加的方法
@Override
public void add(Book book) {
//1.創建sql陳述句
String sql = "insert into t_user values(?,?,?,?)";
//2.呼叫方法實作
int update = jdbcTemplate.update(sql,book.getId(),book.getUsername(),book.getPassword(),book.getEmail());
System.out.println(update);
}
//修改
@Override
public void update(Book book) {
String sql = "update t_user set username=?,password=?,email=? where id=?";
Object[] args = {book.getUsername(),book.getPassword(), book.getEmail(),book.getId()};
int update = jdbcTemplate.update(sql,args);
System.out.println(update);
}
//洗掉
@Override
public void delete(String id) {
String sql = "delete from t_user where id=?";
int update = jdbcTemplate.update(sql,id);
System.out.println(update);
}
//查詢表記錄數
@Override
public int selectCount() {
String sql = "select count(*) from t_user";
Integer count = jdbcTemplate.queryForObject(sql,Integer.class);
return count;
}
}
BookService.java
package com.service;
import com.dao.BookDao;
import com.entity.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BookService {
//注入dao
@Autowired
private BookDao bookDao;
//添加的方法
public void addBook(Book book){
bookDao.add(book);
}
//修改的方法
public void updateBook(Book book){
bookDao.update(book);
}
//洗掉的方法
public void deleteBook(String id){
bookDao.delete(id);
}
//查詢表記錄數
public int findCount() {
return bookDao.selectCount();
}
}
BookDao.java
package com.dao;
import com.entity.Book;
public interface BookDao {
//添加的方法
void add(Book book);
//修改的方法
void update(Book book);
//洗掉的方法
void delete(String id);
//查詢表記錄數
int selectCount();
}
Test:
package com.test;
import com.entity.Book;
import com.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TsetBook {
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService",BookService.class);
//添加
// Book book = new Book();
// book.setId("7");
// book.setUsername("c");
// book.setPassword("c");
// book.setEmail("[email protected]");
// bookService.addBook(book);
//修改
// Book book = new Book();
// book.setId("7");
// book.setUsername("python");
// book.setPassword("p");
// book.setEmail("[email protected]");
// bookService.updateBook(book);
//
//洗掉
//bookService.deleteBook("7");
//查詢回傳某個值
int count = bookService.findCount();
System.out.println(count);
}
}
運行結果:
資訊: {dataSource-1} inited
5
6.JdbcTemplate操作資料庫(查詢回傳物件)
(1)場景:查詢圖書詳情
(2)JdbcTemplate實作查詢回傳物件
queryForObject(String sql,RowMapper<T> rowMapper,Object... args)
有三個引數:
?第一個引數:sql陳述句
?第二個引數:RowMapper是介面,回傳不同型別資料,使用這個介面里面實作類完成資料的封裝
?第三個引數:sql陳述句值
BookDaoImpl.java
//查詢回傳物件
@Override
public Book findBookInfo(String id) {
String sql = "select * from t_user where id=?";
//呼叫方法
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
return book;
}
BookService.java
//查詢回傳物件
public Book findOne(String id){
return bookDao.findBookInfo(id);
}
BookDao.java
//查詢回傳物件
Book findBookInfo(String id);
Test:
//查詢回傳物件
Book book =bookService.findOne("1");
System.out.println(book);
運行結果:
資訊: {dataSource-1} inited
Book{id='1', username='admin', password='123', email='[email protected]'}
7.JdbcTemplate操作資料庫(查詢回傳集合)
(1)場景:查詢圖書串列分頁
(2)呼叫JdbcTemplate方法實作查詢回傳集合
query(String sql,RowMapper<T> rowMapper,Object... args)
有三個引數:
?第一個引數:sql陳述句
?第二個引數:RowMapper是介面,回傳不同型別資料,使用這個介面里面實作類完成資料的封裝
?第三個引數:sql陳述句值
BookDaoImpl.java
//查詢回傳集合
@Override
public List<Book> findAllBook() {
String sql = "select * from t_user";
//呼叫方法
List<Book> bookList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
return bookList;
}
BookService.java
//查詢回傳集合
public List<Book> findAll(){
return bookDao.findAllBook();
}
BookDao.java
//查詢回傳集合
List<Book> findAllBook();
Test:
//查詢回傳集合
List<Book> all = bookService.findAll();
System.out.println(all);
}
運行結果:
資訊: {dataSource-1} inited
[Book{id='1', username='admin', password='123', email='[email protected]'}, Book{id='2', username='dd', password='123', email='[email protected]'}, Book{id='4', username='dd1', password='123', email='[email protected]'}, Book{id='5', username='hh', password='123', email='[email protected]'}, Book{id='6', username='java', password='j', email='[email protected]'}]
8.JdbcTemplate操作資料庫(批量操作)
(1)批量操作:操作表里面的多條資料
(2)JdbcTemplate實作批量添加操作
batchUpdate(String sql,List<Object[]> batchArgs)
有二個引數:
?第一個引數:sql陳述句
?第二個引數:List集合,添加多條記錄數
BookDaoImpl.java
//批量添加
@Override
public void batchAddBook(List<Object[]> batchArgs) {
String sql = "insert into t_user values(?,?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql,batchArgs);
System.out.println(Arrays.toString(ints));
}
BookService.java
//批量添加
public void batchAdd(List<Object[]> batchArgs){
bookDao.batchAddBook(batchArgs);
}
BookDao.java
//批量添加
public void batchAddBook(List<Object[]> batchArgs);
Test:
//批量添加
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"7","python","p","[email protected]"};
Object[] o2 = {"8","c#","cc","[email protected]"};
batchArgs.add(o1);
batchArgs.add(o2);
//呼叫批量添加
bookService.batchAdd(batchArgs);
運行結果:
資訊: {dataSource-1} inited
[1, 1]
(3)JdbcTemplate實作批量修改操作
BookDaoImpl.java
//批量修改
@Override
public void batchUpdateBook(List<Object[]> batchArgs) {
String sql = "update t_user set username=?,password=?,email=? where id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
BookService.java
//批量修改
public void batchUpdate(List<Object[]> batchArgs){
bookDao.batchUpdateBook(batchArgs);
}
BookDao.java
//批量修改
void batchUpdateBook(List<Object[]> batchArgs);
Test:
//批量修改
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"ddd","d","[email protected]","7"};
Object[] o2 = {"fff","f","[email protected]","8"};
batchArgs.add(o1);
batchArgs.add(o2);
//呼叫批量修改
bookService.batchUpdate(batchArgs);
運行結果:
資訊: {dataSource-1} inited
[1, 1]
(4)JdbcTemplate操作資料庫(批量洗掉)
BookDaoImpl.java
//批量洗掉
@Override
public void batchDeleteBook(List<Object[]> batchArgs) {
String sql = "delete from t_user where id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString(ints));
}
BookService.java
//批量修改
public void batchDelete(List<Object[]> batchArgs){
bookDao.batchDeleteBook(batchArgs);
}
BookDao.java
//批量洗掉
void batchDeleteBook(List<Object[]> batchArgs);
Test:
//批量洗掉
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"2"};
Object[] o2 = {"4"};
batchArgs.add(o1);
batchArgs.add(o2);
//呼叫批量洗掉
bookService.batchDelete(batchArgs);
運行結果:
資訊: {dataSource-1} inited
[1, 1]
五、事物管理
1.事務概念
(1)什么是事務
? 1)事務是資料庫操作最基本單元,邏輯上一組操作,要么都成功,如果有一個失敗所有操作都失敗
? 2)典型場景:銀行轉賬
(2)事務四個特性(ACID)
? 1)原子性
? 2)一致性
? 3)隔離性
? 4)持久性
2.事務操作(搭建事務操作環境)

(1)創建資料庫表,添加記錄

(2)創建service,搭建dao,完成物件創建和注入關系
? 1)service注入dao,在dao注入JdbcTemplate,在JdbcTemplate注入DataSource
? UserService.java
package com.service;
import com.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
//注入aop
@Autowired
private UserDao userDao;
}
UserDaoImpl.java
package com.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
}
(3)在dao創建兩個方法:多錢和少錢的方法,在service創建(轉賬的方法)
UserService.java
package com.service;
import com.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
//注入aop
@Autowired
private UserDao userDao;
//轉賬的方法
public void accountMoney(){
//dd少100
userDao.reduceMoney();
//df多100
userDao.addMoney();
}
}
UserDao.java
package com.dao;
public interface UserDao {
//多錢
public void addMoney();
//少錢
public void reduceMoney();
}
UserDaoImpl.java
package com.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
//多錢
@Override
public void addMoney() {
String sql = "update count set money=money+? where username=?";
JdbcTemplate.update(sql,100,"df");
}
//少錢
@Override
public void reduceMoney() {
String sql = "update count set money=money-? where username=?";
JdbcTemplate.update(sql,100,"dd");
}
}
Test:
package com.test;
import com.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestBook {
@Test
public void TsetUser(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userservice",UserService.class);
userService.accountMoney();
}
}
六、Spring 5 新特性
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/510849.html
標籤:Java
上一篇:AUSTOj4
下一篇:Redis詳解
