一、前置知識的介紹
1.Spring
輕量級的 DI / IoC 和 AOP 容器的開源框架
容器的開源框架網址:https://spring.io/projects/spring-framework
作用:可簡化管理創建和組裝對象之間的依賴關系
將controller----->service------->dao層的依賴配置使用Spring注解來實現自動注入。
2.Spring IOC
Inverse of Control(控制反轉)是一種設計思想 將程序中手動創建對象的流程,交由Spring框架來管理,即把創建對象的控制權反轉給Spring框架,由Spring統一管理。把spring ioc 當成一個容器,里面存儲管理的對象稱為Bean
3.DI
Dependency Injection ,依賴注入,動態地將對象某種依賴關系注入到對象之中.
4.Bean屬性scope
singleton:單例, 默認值,調用getBean方法返回是同一個對象,spring的IOC容器中只會存在一個該bean。
prototype: 多例,調用getBean方法創建不同的對象,會頻繁的創建和銷毀對象造成很大的開銷。
5.AOP
Aspect Oriented Program 面向切面編程,在不改變原有邏輯上增加額外的功能。
把功能分兩個部分,核心關注點(業務的主要功能)與橫切關注點(非核心、額外增加的功能)
通知 Advice:在特定的切入點上執行的增強處理;類型包括@Before前置通知-在執行目標方法之前運行,@After后置通知、@AfterReturning返回通知-在目標方法正常返回值后運行、@AfterThrowing異常通知-在目標方法出現異常后運行、@Around環繞通知-在目標方法完成前、后做增強處理 。
連接點 JointPoint:業務流程在運行過程中需要插入切面的具體位置
切入點 Pointcut:通過特定的規則來篩選連接點, 就是Pointcut,選中那幾個你想要的方法
切面 Aspect:定義了切入點+通知的一個類?。
目標 target:目標類,真正的業務邏輯。
織入 Weaving:把切面(某個類)應用到目標函數的過程稱為織入。
AOP代理:對AOP框架創建對象的加強,主要有JDK動態代理與CGLIB代理
//目標類 VideoOrderService; 里面每個方法都是連接點(addOrder,findOrderById,delOrder,updateOder);
//切入點是CUD類型的方法,R讀取的不作為切入點 ,CRDU全稱:增加(Create)、讀取查詢(Retrieve)、更新(Update)和刪除(Delete)
//目標類
VideoOrderService{
//新增訂單
addOrder(){ }
//查詢訂單
findOrderById(){}
//刪除訂單
delOrder(){}
//更新訂單
updateOrder(){} }
//權限切面類 = 切入點+通知
PermissionAspects{
//切入點 定義了什么地方
@Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")
public void pointCut(){}
//before 通知 表示在目標方法執行前切入, 并指定在哪個方法前切入
//什么時候,做什么事情
@Before("pointCut()") public void permissionCheck(){
System.out.println("在 xxx 之前執行權限校驗"); } .... }
//日志切面類 = 切入點+通知 LogAspect{
//切入點 定義了什么地方 @Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")
public void pointCut(){}
//after 通知 表示在目標方法執行后切入, 并指定在哪個方法前切入
//什么時候,做什么事情
@After("pointCut()") public void logStart(){
System.out.println("在 xxx 之后記錄日志"); } .... }
6.切入點表達式
格式
execution(訪問修飾符 返回值類型 包和類 方法
7.代理
創建代理對象來控制對原對象,通過代理類這中間一層,能有效控制對委托類對象的直接訪問
靜態代理-由程序創建或特定工具自動生成源代碼;
動態代理-在程序運行時,運用反射機制動態創建而成,主要有JDK動態代理與CGLIB代理。?
二、搭建項目
1.快速上手搭建
創建maven項目
添加maven依賴可參照網站:https://mvnrepository.com/
在pom.xml中添加依賴
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.5.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-core --><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.5.RELEASE</version></dependency><!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.5.RELEASE</version></dependency>
開發實體層(domain)
package net.xdclass.sp.domain;public class Video {private int id;private String title;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {this.title = title;}
}
創建配置文件
applicationContext.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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean name="video" class="net.xdclass.sp.domain.Video" scope="prototype"><property name="name" value="tom"/><property name="id" value="23"/></bean></beans>
開發啟動類
獲取bean,調用對象中的方法
package net.xdclass.sp;import net.xdclass.sp.domain.Video;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App {public static void main(String [] args){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");Video video = (Video)applicationContext.getBean("video");System.out.println(video.getTitle());}}
三、spring的使用介紹
1.使用xml配置?
Bean對象的常見注入方式
作用范圍通過scope來指定,singleton-單例, 默認值;prototype:-多例
使用set方法注入
<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton"><property name="id" value="9"/><property name="title" value="Spring 5.X課程" /></bean>
使用帶參的構造函數注入
<bean id="video" class="net.xdclass.sp.domain.Video" ><constructor-arg name="title" value="面試專題課程第一季"></constructor-arg></bean>
POJO類型注入(property 沒有使用value屬性,而是使用了ref屬性)
<bean id="video" class="net.xdclass.sp.domain.Video" ><constructor-arg name="title" value="面試專題課程第一季"></constructor-arg></bean><bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" ><property name="id" value="8" /><property name="outTradeNo" value="23432fnfwedwefqwef2"/><property name="video" ref="video"/></bean>
?list類型與Map類型的注入
<bean id="video" class="net.xdclass.sp.domain.Video" ><!--list類型注入--><property name="chapterList"><list><value>第一章SpringBoot</value><value>第二章Mybatis</value><value>第三章Spring</value></list></property><property name="videoMap"><map><entry key="1" value="SpringCloud課程"></entry><entry key="2" value="面試課程"></entry><entry key="3" value="javaweb課程"></entry></map></property>
</bean>
在實體類中添加返回方法
public class Video {private int id;private String title;private List<String> chapterList;private Map<Integer,String> videoMap;//省略set get方法
}
優化配置
兩個類之間大多數的屬性都相同,可通過parent標簽來避免重復配置
<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton"><property name="id" value="9"/><property name="title" value="Spring 5.X課程" /></bean><bean id="video2" class="net.xdclass.sp.domain.Video2" scope="singleton" parent="video"><!--只需要配置不同的屬性即可--><property name="summary" value="這個是summary"></property></bean>
?兩個類之間存在屬性依賴,可通過depend-on實現實例化的順序
<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton"><property name="id" value="9"/><property name="title" value="Spring 5.X課程" /></bean><!--設置兩個bean的關系,video要先于videoOrder實例化--><bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" depends-on="video"><property name="id" value="8" /><property name="outTradeNo" value="23432fnfwedwefqwef2"/><property name="video" ref="video"/>
</bean>
Bean生命周期
通過init-method與destroy-method來指定
<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton" init-method="init" destroy-method="destroy">
自動裝配屬性autowire
可為一個 bean 定義指定自動裝配模式,可設置的值有no-不開啟、byName-據id注入對應屬性、byType-據類型注入屬性、constructor-據構造函數注入屬性。
<bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" autowire="byName">
?2.使用注解配置
開啟注解的配置
package net.xdclass.sp;import net.xdclass.sp.aop.AnnotationAppConfig;
import net.xdclass.sp.domain.Video;
import net.xdclass.sp.domain.VideoOrder;
import net.xdclass.sp.service.VideoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class App {public static void main(String[] args) {//1.加載注解配置類AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationAppConfig.class);//2.通過@Component獲取beanVideoService videoService = (VideoService) context.getBean("videoService");//3.調用Bean對象的業務方法videoService.findById(2);}}
- 配置Bean對象
通過@Component("Bean對象名") 通用組件 細分: @Controller (用于web層) @Service (用于service層) @Repository (用于dao倉庫層)
domain層
package net.xdclass.sp.domain;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;@Component
public class Video {private int id;private String title;public void init(){System.out.println("video類 init 方法被調用");}public void destroy(){System.out.println("video類 destroy 方法被調用");}public Video(){//System.out.println("video 空構造函數被調用");}public Video(String title){//System.out.println("video 帶參數構造函數被調用");this.title = title;}public int getId() {return id;}public void setId(int id) {//System.out.println("Video setId方法被調用");this.id = id;}public String getTitle() {return title;}public void setTitle(String title) {//System.out.println("Video setTitle方法被調用");this.title = title;}
}
controller層:未指定時,默認為方法名 + 第一個字母小寫 作為bean的名稱
package net.xdclass.sp.controller;import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;@Controller
public class VideoController {
}
service層
package net.xdclass.sp.service;import net.xdclass.sp.config.CustomConfig;
import net.xdclass.sp.dao.VideoDao;
import net.xdclass.sp.domain.Video;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;//@Component("videoService")
@Service("videoService")
public class VideoServiceImpl implements VideoService {@Autowired//實現Bean對象的注入private VideoDao videoDao;@Autowiredprivate CustomConfig customConfig;public int save(Video video) {System.out.println("保存video");return 1;}public Video findById(int id) {System.out.println("根據id找視頻");videoDao.test();System.out.println(customConfig.getHost());try {Thread.sleep(2000L);} catch (InterruptedException e) {e.printStackTrace();}return new Video();}
}
dao層
package net.xdclass.sp.dao;import org.springframework.stereotype.Repository;@Repository("videoDao")
public class VideoDao {public void test(){System.out.println("video Dao test ");}}
- 注入Bean對象?
類型注入@Autowired;名稱注入@Qualifier
bean生命周期
@PostConstruct初始化、@PreDestroy銷毀
bean作用范圍
@scope注解,singleton-單例, 默認值;prototype:-多例
package net.xdclass.sp.domain;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;@Component
//@Scope("prototype")
@Scope
public class Video {private int id;private String title;@PostConstructpublic void init(){System.out.println("video類 init 方法被調用");}@PreDestroypublic void destroy(){System.out.println("video類 destroy 方法被調用");}}
定義第三方bean
@Configuration標注在類為spring容器(相當于類在spring的xml配置文件中的配置)
@bean標注方法為一個Bean對象,將Bean對象交給Spring管理,Spring將Bean對象放入IOC容器中。
注意:bean都需要在@Configuration注解下進行創建
package net.xdclass.sp.config;import net.xdclass.sp.domain.VideoOrder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;@Configuration
public class AppConfig {//使用@bean注解,表明這個bean交個spring 進行管理// 如果沒有指定名稱,默認采用 方法名 + 第一個字母小寫 作為bean的名稱@Bean(name = "videoOrderName",initMethod = "init",destroyMethod = "destroy")@Scopepublic VideoOrder videoOrder(){return new VideoOrder();}}
自動映射配置文件
@PropertySource,指定加載配置文件,實現將配置文件映射到實體類;
@Value映射到具體的java屬性
創建配置文件config.properties
server.host=127.0.0.1server.port=999
映射到實體類中
package net.xdclass.sp.config;import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;@Configuration//1.指定這個類是一個配置類
@PropertySource(value = {"classpath:config.properties"})//2.指定配置文件
public class CustomConfig {@Value("${server.host}")//3.注入配置文件中的屬性值private String host;@Value("${server.port}")private int port;public String getHost() {return host;}public void setHost(String host) {this.host = host;}public int getPort() {return port;}public void setPort(int port) {this.port = port;}
}
?四、事務管理
1.概念
多個操作,要么同時成功,要么失敗后一起回滾。包括A(Atomic-原子性)C(Consistency-一致性)I(Isolation-隔離性)D(Durability-持久性)四種特性.
2.方法
beginTransaction()、commit()、rollback()
3.事務傳播
在開始當前事務之前,一個事務上下文已經存在,實現指定一個事務性方法的執行行為
4.事務隔離
是指若干個并發的事務之間的隔離程度
五、小結?
? ? ? ?與上一篇MyBatis+Maven開發后端比較,?在MyBatis中配置xml著重在于去存放sql語句,通過調用層層封裝的方法來進行操作;而Spring中配置xml著重在于配置Bean對象,通過獲取Bean調用其中的方法來進行操作。