主頁 > 後端開發 > ??爆肝萬字!一文最全總結之Spring從入門到入土??(建議收藏)

??爆肝萬字!一文最全總結之Spring從入門到入土??(建議收藏)

2021-10-06 08:16:00 後端開發

在這里插入圖片描述

文章目錄

  • 前言
  • 1. Spring概述
    • 1.1 介紹
  • 2. IoC入門
    • 2.1 什么是IoC
    • 2.2 IoC入門案例1(基礎案例)
    • 2.3 IoC入門案例2(依賴注入)
    • 2.4 IoC入門案例3(面向介面編程)
    • 2.5 IoC入門案例4(整合JUnit4)
  • 3. IoC詳解
    • 3.1 Bean的創建
    • 3.2 依賴注入(DI)
      • 3.2.1 按照名稱注入
      • 3.2.2 按照型別注入
      • 3.2.3 普通資料注入
      • 4 properties資料注入
    • 1.1 @Bean(工廠Bean)
      • 3.2.5 基本使用:型別注入
      • 3.2.6 基本使用:指定名稱注入
      • 3.2.7 依賴注入:參考型別
      • 3.2.8 依賴注入:簡單型別
    • 1.1 Bean的作用域
    • 3.3 生命周期
      • 3.3.1 實體Bean
      • 3.3.2 工廠Bean
  • 4. AOP
    • 4.1 AOP概述
      • 4.1.1 什么是AOP
      • 4.1.2 快速入門1
      • 4.1.3 AOP作用和優勢
      • 4.1.4 快速入門2
      • 4.1.5 快速入門3
      • 4.1.6 AOP實作方法
    • 4.2 相關AOP術語
    • 4.3 相關注解
      • 4.3.1 切入點運算式
      • 4.3.2 通知方法
      • 4.3.3 抽取公共 切入點
    • 4.4 完整通知演示
      • 4.4.1 AOP編程
      • 4.4.2 目標介面和類
  • 5. 整合MyBatis
    • 5.1 環境搭建
      • 5.1.1 匯入 pom相關的依賴
      • 5.1.2 組態檔
      • 5.1.3 創建資料庫和表
      • 5.1.4 創建domain
    • 5.2 撰寫dao和service
      • 5.2.1 撰寫dao介面
      • 5.2.2 撰寫service介面
      • 5.2.3 撰寫Service實作類
    • 5.3 配置類
      • 5.3.1 spring配置類
      • 5.3.2 mybatis配置類【新內容】
    • 5.4 測驗類
      • 5.4.1 方式1:整合Junit
      • 5.4.2 方式2:手動創建工廠
      • 5.4.3 完整的UserService
  • 6. 事務管理
    • 6.1 案例:轉賬
      • 6.1.1 需求描述:
      • 6.1.2 環境搭建
      • 6.1.3 撰寫domain
      • 6.1.4 撰寫dao
      • 6.1.5 撰寫service
      • 6.1.6 測驗
      • l 事務的概述
    • 6.2 事務概述
    • 6.3 Spring事務相關的術語
      • 6.3.1 事務平臺管理器: PlatformTransactionManager
    • 6.4 事務入門
      • 6.4.1 修改配置類
      • 6.4.2 修改Service
    • 6.5 事務高級 ( 面試必背 )
      • 6.5.1 事務特性:ACID
      • 6.5.2 并發訪問問題
      • 6.5.3 隔離級別:解決問題
      • 6.5.4 術語
      • 6.5.5 定義物件:概述 TransactionDefinition
      • 6.5.6 定義物件:只讀
      • 6.5.7 定義物件:超時
      • 6.5.8 定義物件:隔離級別
      • 6.5.9 定義物件:傳播行為 ( Spring特有 )
  • 7. 附錄

前言

上回為各位分享了《六萬字最全總結Java資料庫編程MyBatis》沒有學過的同學,建議先學MyBatis,這次在此基礎上我們來學習經典框架之Spring!

??爆肝六萬字最全總結Java資料庫編程MyBatis(建議收藏)

相關資料:
檔案:02_Spring組態檔和配置類

1. Spring概述

1.1 介紹

Spring框架是企業使用最多的框架,沒有之一,Spring是一站式框架,稱之為一站式框架的原因是Spring可以整合其他框架,

img

要學習Spring的內容如下:

l Spring IoC:物件工廠及依賴注入;

l Spring AOP:面向切面編程技術,為Spring事務管理打下基礎,

l Spring Transaction management:Spring事務管理,

l Spring Web MVC(不包含在本課程內,后面單獨學習):簡稱Spring MVC框架,用來簡化JavaWEB開發,當使用Spring MVC框架后,就不用再撰寫Servlet了,也就不再需要itcast-tools工具中BaseServlet類了,

l Spring與其他框架整合:因為我們只學習過MyBatis框架,所以當前我們只學習Spring整合MyBatis框架,

2. IoC入門

2.1 什么是IoC

Spring IoC的核心如下:

l 工廠負責物件生命周期的管理;(spring管理創建與銷毀)

l 物件的依賴由工廠完成注入,(spring維護物件間關系)

Spring提出了物件工廠的概念,由Spring工廠來管理物件的生命周期,所謂物件生命周期指的是從物件的創建一直到物件的銷毀都由Spring來管理,我們無需再自己new物件,而是從Spring工廠中獲取需要的物件,甚至物件的依賴也由工廠來注入,無需手動注入依賴,

Spring工廠是ApplicationContext介面,通常我們使用的是AnnotationConfigApplicationContext類,其中Spring工廠內部是通過Map型別來維護的,

keyvalue
“userDao1”UserDao實體
“userService1”UserService實體

當我們需要獲取工廠中的實體時,只需要呼叫工廠的getBean(“id”)即可,

?

@Test
	public void test3() {
		AnnotationConfigApplicationContext context = ...
		UserDao userDao = (UserDao) context.getBean("userDao1");
		...
	}

img

2.2 IoC入門案例1(基礎案例)

入門案例1 使用IOC的方式創建UserDao物件 呼叫查詢所有方法

思路:

  1. 目標類上加@Component

創建UserDao類, 書寫方法 findAll ,在類上添加注解@component(”名字”),用來告知spring可以通過指定名字來創建該UserDao物件

  1. 配置類添加@Configuration 和 @ComponentScan

創建配置類 [SpringConfiguration,類上添加@Configuration注解和@ComponentScan注解.[(作用是用來告知Spring該類是配置類,并要掃描的包有哪些)]

  1. 測驗類通過ApplicationContext的getBean(“名字”)獲取物件

img

案例步驟如下:

l 配置類(SpringConfiguration)

l UserDao類

l UserDaoTest類

img

2.2.1 下載Spring

官網:http://spring.io/

下載地址:

http://repo.springsource.org/libs-release-local/org/springframework/spring

解壓:(Spring目錄結構:)

docs :API和開發規范.

libs :jar包和原始碼.

schema :約束.

img

我們上課使用的maven,使用老師發的pom檔案即可.

Pom檔案也可以從本檔案結尾的附錄的pom01-Spring入門拷貝

2.2.2 配置類(SpringConfiguration)

任何Spring專案都建議創建配置類,它提供了Spring工廠最基本的配置資訊,本案例中該類沒有任何內容,只需要添加兩個注解,

SpringConfiguration.java

package com.czxy.comfig;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan(basePackages = {"com.czxy.dao"})
@Configuration
public class SpringConfiguration {


}

l 其中@Configuration注解告知Spring當前類是一個配置類;

l 其中@componentScan注解告知Spring要掃描的包,Spring會掃描并加載指定包下所有類中的注解,

2.2.3 UserDao.java

我們需要在撰寫UserDao類,同時希望Spring去創建該類實體并添加到工廠中,這需要在類上添加@Component注解,同時指定實體的id,Spring會掃描到UserDao類上的@Component注解,

UserDao.java

package com.czxy.dao;

import org.springframework.stereotype.Component;

@Component("ud")
public class UserDao {

   public void findAll(){

      System.out.println("查詢所有");

   }
}

2.2.4 UserDaoTest測驗類

在測驗類中我們需要先創建工廠物件,然后從工廠物件中獲取UserDao物件實體,

UserDaoTest.java

package com.czxy.test;

import com.czxy.comfig.SpringConfiguration;
import com.czxy.dao.UserDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestA {


   public static void main(String[] args) {
      
      ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfiguration.class);
      UserDao userDao = (UserDao) applicationContext.getBean("ud");// new UserDao();
      userDao.findAll();
      
   }
}

2.3 IoC入門案例2(依賴注入)

入門案例2中我們需要創建UserService類,但我們知道UserServce一定會依賴UserDao類,然后我們讓Spring工廠幫助我們完成依賴注入,

img

步驟如下:

l 定義UserService類并添加@Component注解;

l 在UserService類中添加private UserDao userDao依賴;

l 在userDao成員上添加@Resource注解指定依賴,

SpringConfiguration.java

package com.czxy.comfig;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@ComponentScan(basePackages = {"com.czxy.dao","com.czxy.service"})
@Configuration
public class SpringConfiguration {


}

UserService.java

package com.czxy.service;

import com.czxy.dao.UserDao;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component("us")
public class UserService {
   @Resource(name = "ud")
   private UserDao  userDao ;//= new UserDao();

   public void findAllUsers(){
      System.out.println("開始查找");
      userDao.findAll();
      System.out.println("查找結束");
   }
}

測驗類

@Test
public void test02(){
   ApplicationContext applicationContext  = new AnnotationConfigApplicationContext(SpringConfiguration.class);
   UserService userService = (UserService) applicationContext.getBean("us");
   userService.findAllUsers();
}

測驗結果:

img

2.4 IoC入門案例3(面向介面編程)

? 入門案例3提供dao的介面和實作類、提供service的介面和實作類,程式之間使用介面,將所有實作類交予spring管理,完成程式間的解耦,

img

img

l 步驟如下

n 撰寫UserDao介面和實作類,并在實作類中添加@Component注解

n 撰寫UserService介面和實作類,并在實作類中添加@Component注解

n 在userDao成員變數中添加@Resource注解,注入dao的實作類,

n 撰寫配置類

n 編程測驗類

l dao介面和實作類

public interface UserDao {
   public void findAll();
}

@Component("userDaoImpl")
public class UserDaoImplA implements UserDao {

   public void findAll(){
      System.out.println("A方式 查詢所有");
}
}

l service介面和實作類

public interface UserService {
   public void findAllUsers();
}
@Component("userServiceImpl")
public class UserServiceImplA implements UserService {

   @Resource(name = "userDaoImpl")
   private UserDao userDao ;//= new UserDao();

   public void findAllUsers(){
      System.out.println("開始查找");
      userDao.findAll();
      System.out.println("查找結束");
   }
}

l 配置類 不變

@ComponentScan(basePackages = {"com.czxy.dao","com.czxy.service"})
@Configuration
public class SpringConfiguration {


}

l 測驗類

@Test

@Test
public void test03(){
   ApplicationContext applicationContext  = new AnnotationConfigApplicationContext(SpringConfiguration.class);
   UserService userService = (UserService) applicationContext.getBean("userServiceImpl");
   userService.findAllUsers();
}

測驗結果:

img

2.5 IoC入門案例4(整合JUnit4)

l 修改測驗

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(classes={SpringConfigruation.class}) 
public class UserDaoTest {
	
	@Resource(name="userService1")  
	private UserService userService;
	
	@Test
	public void testFindAll(){
		userService.findAll();
	}
}

3. IoC詳解

3.1 Bean的創建

前面已經學習了創建Bean的注解@Component,Spring還提供了一些衍生注解,

注解描述
@Component將修飾的資源交予spring管理,value屬性:為資源命名(唯一標識)
@Controller衍生注解,與@Component作用和屬性相同,特用于修飾表示層的資源,
@Service衍生注解,與@Component作用和屬性相同,特用于修飾業務邏輯層的資源,
@Repository衍生注解,與@Component作用和屬性相同,特用于修飾資料訪問層的資源,

示例: 分別使用不同名字的注解來設定回應的類

@Repository("userDao1")
public class UserDaoImpl implements UserDao {
	public void findAll(){
		System.out.println("入門案例");
	}
}

@Service("userService1")
public class UserServiceImpl implements UserService{
	
	@Resource(name="userDao1") 
	private UserDao userDao;
	
	public void findAll(){
		System.out.println("user service ...");
		userDao.findAll();
	}
}

l 以上4個注解修飾的類,我們通常稱為注冊bean,目的是將某類的實體物件,添加到spring容器中,

3.2 依賴注入(DI)

注解描述修飾位置
@Resource(name=”…”)按照指定名稱注入物件欄位、setter方法
@ Resource按照型別注入物件欄位、setter方法
@Value注入簡單值欄位、setter方法、引數
@PropertySource加載properties組態檔

3.2.1 按照名稱注入

示例: 按照名稱來注入userDao物件

?dao
@Repository("userDao1")
public class UserDaoImpl implements UserDao {
	public void findAll(){
		System.out.println("入門案例");
	}
}
?service
@Service("userService1")
public class UserServiceImpl implements UserService{
	
	@Resource(name="userDao1")
	private UserDao userDao;
	
	public void findAll(){
		System.out.println("user service ...");
			userDao.findAll();
	}
}

3.2.2 按照型別注入

示例: 分別創建dao ,service ,和測驗類,按照型別注入對應的物件

?dao
@Repository
public class UserDaoImpl implements UserDao {
	public void findAll(){
		System.out.println("入門案例");
	}
}
?service
@Service
public class UserServiceImpl implements UserService{
	
	@Resource
	private UserDao userDao;
	
	public void findAll(){
		System.out.println("user service ...");
		userDao.findAll();
	}
}

?測驗
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfigruation.class})
public class UserDaoTest {
	
	@Resource
	private UserService userService;
	
	@Test
	public void testFindAll(){
		userService.findAll();
	}
}

3.2.3 普通資料注入

示例:字串型別的成員變數和方法引數注入資料.

?固定值注入
public class SpringConfigruation {
	
	@Value("com.mysql.jdbc.Driver")
	private String driver;
	
	@Value("jdbc:mysql://127.0.0.1:3306/crm_ssm_v1_0")
	public void setUrl(String url){
		System.out.println("欄位:" + driver);
		System.out.println("方法:" + url);
	}
}
?測驗
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfigruation.class})
public class UserDaoTest {
	
	@Test
	public void testFindAll() throws SQLException{
	}
}

4 properties資料注入

需求: 把properties檔案中的資料讀取出來,在測驗類中展示

總體思路:

使用@PropertySource加載properties組態檔,“classpath:”固定前綴,表示從類路徑下加載組態檔,

@Value(${jdbc.driver}) 獲得組態檔中指定key的內容

? 默認:將整個運算式進行注入,及 driver變數的值是 ${jdbc.driver}

? 固定代碼:必須配置PropertySourcesPlaceholderConfigurer實體,

專案結構如下:

img

jdbc.properties組態檔:

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://127.0.0.1:3306/test1

jdbc.username=root

jdbc.password=1234

?配置類 添加內容
package com.czxy.demo02;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

@Configuration
@PropertySource("classpath:db.properties")
public class SpringConfig02 {

    // 在4.2.4版本讀取properties必須寫,必須要寫的固定格式
    @Bean
    public static PropertySourcesPlaceholderConfigurer create(){
        return  new PropertySourcesPlaceholderConfigurer();
    }
    
}

測驗類: 
package com.czxy.demo02;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig02.class)
public class TestB {

    @Value("${jdbc.driver}")
    private String driverClassName;

    @Value("${jdbc.url}")
    private String url;

    @Test
    public void test01(){
        System.out.println("driverClassName="+driverClassName);
        System.out.println("url="+url);
    }
}

測驗結果:正常獲取資料

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SIWE7Gtr-1633402543916)(C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps7DBD.tmp.jpg)]

1.1 @Bean(工廠Bean)

把別人創建的類,交給IOC管理可以使用方法配合注解@Bean的方式實作.

通過@Component等注解,將我們自己撰寫的物件配置到spring容器中,

通過@Resource等注解,將我們自己撰寫的物件之間的關系配置到spring容器中,

實際開發中,我們經常會遇到某些類不是我們寫的,此時我們希望通過IOC對這種類進行管理,我們就沒法辦在這個類上加@Component等注解了. 這個時候可以創建一個方法在方法上使用@Bean來實作對這些類物件的管理

3.2.5 基本使用:型別注入

? @Bean用于修飾方法 ,將方法創建的物件添加到spring容器

需求: 假設UserDao不是我們寫的類,無法使用@Component注解,

創建一個方法用于獲取UserDao物件

準備如下幾個類

img

UserDao:
package com.czxy.demo03;

public class UserDao {  

    public void findAll(){
        System.out.println("查詢所有 ");
    }
}
SpringConfig03:
package com.czxy.demo03;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig03 {


    @Bean  
    public UserDao getUserDao(){
        return  new UserDao();
    }

}
測驗類: 
package com.czxy.demo03;


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig03.class)
public class TestC {

    @Resource
    private UserDao userDao;

    @Test
    public void test01(){
        userDao.findAll();
    }
}

測驗結果:

img

3.2.6 基本使用:指定名稱注入

上面例子中,在方法上只是書寫了一個@Bean.并沒有給期產生的物件命名如果想命名可以通過如下方式.

@Bean(name=”名字”) 可以為當前物件設定一個名稱,如果沒有使用name設定名稱,默認名為“ 方法名 ”,

需求:

UserDao是個介面,有倆實作類UserDaoImplA和UserDaoImplB, 這三個類假設我們都不能修改.

現在想獲取這倆實作類的物件,交給IOC管理. 設計完成該例子.

專案結構如下:

img

UserDao介面:
package com.czxy.demo04;

public interface UserDao {

    public void findAll();
}
UserDaoImplA實作類:
package com.czxy.demo04;

public class UserDaoImplA implements UserDao {
    @Override
    public void findAll() {
        System.out.println("A 方式實作查詢所有用戶 ");
    }
}
UserDaoImplB實作類:
package com.czxy.demo04;

public class UserDaoImplB implements UserDao {
    @Override
    public void findAll() {
        System.out.println("B 方式實作查詢所有用戶 ");
    }
}

配置類:
package com.czxy.demo04;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig04 {


    @Bean(name ="userDaoImplA" )  
    public UserDao getUserDaoA(){
       return new UserDaoImplA();
    }

    @Bean(name ="userDaoImplB" )  
    public UserDao getUserDaoB(){
        return new UserDaoImplB();
    }
}

測驗類:
package com.czxy.demo04;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig04.class)
public class TestD {

    @Resource(name = "userDaoImplB")  
    private UserDao userDao;

    @Test
    public void test01(){
        userDao.findAll();
    }
}

測驗結果:

userDaoImplB對應:

img

userDaoImplA對應:

img

3.2.7 依賴注入:參考型別

當某一個方法的引數是一個被IOC管理的物件時,可以通過@Bean的方式,自動注入該物件.

如UserDao物件被IOC管理了. 那么 若有方法 形如testXXX(UserDao userDao) 則可以在方法上添加@Bean,來自動注入UserDao物件.

示例1:

把UserDao交給IOC

在配置類中書寫一個方法show(UserDao userDao),完成自動注入,在測驗類中進行測驗.

img

代碼詳情:
UserDao 
package com.czxy.demo06;

import org.springframework.stereotype.Repository;

@Repository  
public class UserDao {

    public void findAll(){

        System.out.println("查詢所有");
    }
}

配置類:SpringConfig06
package com.czxy.demo06;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;

import javax.annotation.Resource;

@Configuration
@ComponentScan(basePackages = "com.czxy.demo06")
public class SpringConfig06 {



    @Bean
    public String show(UserDao userDao){  

        System.out.println("完成自動注入:"+userDao);
        //測驗呼叫userDao方法
        userDao.findAll();

        return  null;
    }

}
測驗類: 
package com.czxy.demo06;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig06.class)
public class TestA1 {


    @Test
    public void test02(){
        //無需書寫任何代碼, 單純執行
        //該方法就會看到自動注入UserDao
    }

}

測驗結果:

img

可以看到 完成了自動注入.

示例2:

把UserDao物件存放到spring容器中, 然后再UserService方法中要使用UserDao,此時可以直接把UserDao當做引數傳遞到方法中

`

img

配置類:
package com.czxy.demo02.config;

import com.czxy.demo02.dao.UserDao;
import com.czxy.demo02.dao.UserDaoImpl;
import com.czxy.demo02.service.UserService;
import com.czxy.demo02.service.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = {"com.czxy.demo02"})
public class SpringConfiguration {

   @Bean 
   public UserDao getUserDao(){
      return  new UserDaoImpl();
   }

   @Bean 
   public UserService getUserService(UserDao userDao){
      System.out.println(userDao);
      return new UserServiceImpl();
   }

}



?測驗類
package com.czxy.demo02.test;


import com.czxy.demo02.config.SpringConfiguration;
import com.czxy.demo02.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class TestA {

   @Resource
   public UserService userService;

   @Test
   public void test01(){
      System.out.println(userService);
   }
}

測驗結果:

img

3.2.8 依賴注入:簡單型別

需求: 把properties檔案中的字串 以簡單型別的方式添加到引數中 列印對應的值.

l 配置類

img

相應代碼:

@PropertySource("classpath:db.properties")
public class SpringConfiguration2 {

   @Bean
   public static PropertySourcesPlaceholderConfigurer create(){
      return new PropertySourcesPlaceholderConfigurer();
   }

   @Bean
   public UserService createUserService(@Value("${jdbc.username}") String name, @Value("${jdbc.password}") String pwd){  
      System.out.println("name = "+name+" pwd ="+pwd);
      return new UserServiceImpl();
   }

}

l 測驗類

img

代碼:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration2.class)
public class TestB {

   @Resource
   private UserService userService;

   @Test
   public void test01(){
      System.out.println(userService);
   }
}

測驗結果:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-3KBzWRNK-1633402543928)(C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps7DD8.tmp.jpg)]

1.1 Bean的作用域

? 通過@Scope可以Bean的作用域,也就是通知spring是否每次都創建新物件,

注解描述取值
@Scope用于設定Bean的作用域singleton :默認值,單例的.prototype :多例的.

單例模式: 整個IOC容器中只有該物體類的一個物件

多例模式: 整個IOC容器中該物體類有多個物件

img

img

示例:

搞一個User類,在配置類中設定單例模式和多例模式,創建兩個物件觀察效果.

配置類:

img

測驗類:

img

單例模式結果: 地址編號相同,說明是用的同一個物件

img

保持測驗類不變,只更改為多例模式

img

測驗結果:列印的兩個地址編號不同,說明IOC容器中有多個物件

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WWrI1INl-1633402543932)(C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps7DEF.tmp.jpg)]

l 其他取值(了解)

  1. request :WEB專案中,Spring創建一個Bean的物件,將物件存入到request域中.

  2. session :WEB專案中,Spring創建一個Bean的物件,將物件存入到session域中.

  3. globalSession :WEB專案中,應用在Portlet環境.如果沒有Portlet環境那么globalSession相當于session

3.3 生命周期

? 生命周期指 單實體 物件由創建到銷毀的整個程序,

? 此處,主要研究初始化方法和銷毀方法,

3.3.1 實體Bean

實體Bean同時2個注解,來控制類中那個方法初始化方法,那個方法是銷毀方法,

注解描述
@PostConstruct初始化方法,專案啟動時執行,只會被呼叫一次,
@PreDestroy銷毀方法,專案關閉時執行,只會被呼叫一次,
?實體Dog
@Component
public class Dog {

   @PostConstruct
   public void init(){
      System.out.println("狗 初始化");
   }

   public void eat(){
      System.out.println("狗 吃吃吃..");
   }

   @PreDestroy
   public void destory(){
      System.out.println("狗 銷毀 ");
   }

}
?配置類
@ComponentScan(basePackages={"com.czxy.domain"})
public class SpringConfigruation {
	
}
?測驗類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration.class)
public class TestC {

   @Resource
   private Dog dog;

   @Test
   public void test01(){
      dog.eat();
   }
}

測驗結果 :

img

3.3.2 工廠Bean

工廠Bean通過@Bean的2個屬性完 成初始化和銷毀方法的配置,

? initMethod:配置初始化方法

? destroyMethod:配置銷毀方法

物體類:

public class Cat {


   public void init(){
      System.out.println("貓 初始化");
   }

   public void eat(){
      System.out.println("貓 吃吃吃..");
   }


   public void destory(){
      System.out.println("貓 銷毀 ");
   }

}

?配置類
@Configuration
@ComponentScan(basePackages = {"com.czxy.demo02"})
public class SpringConfiguration {

   @Bean(initMethod = "init" ,destroyMethod = "destory")
   public Cat getCat(){
      return  new Cat();
   }
}

測驗類:
@Resource
private Cat cat;

@Test
public void test02(){
   cat.eat();
}

測驗結果:

img

4. AOP

4.1 AOP概述

4.1.1 什么是AOP

? AOP:全稱是Aspect Oriented Programming即:面向切面編程,

? 面向切面編程,通過預編譯方式和運行期動態代理實作程式功能的統一維護的一種技術,

? 簡單的說它就是把我們程式重復的代碼抽取出來,在需要執行的時候,使用代理的技術,在不修改原來代碼的基礎上,對已有方法進行增強,

img

4.1.2 快速入門1

需求:

User類中有方法eat . 現在在不修改eat方法的前提下,對eat進行增強. 增強的內容是,在執行eat之前,先執行 沐浴更衣 這個動作.

實作思路:

\1. 搭建基本的測驗 可以在測驗類中執行eat方法

\2. 創建切面類,指明對eat方法進行增強;

img

具體代碼如下: 在書寫代碼之前記得在pom檔案添加spring相關的依賴.

img

User類
@Component 
public class User {

   public void eat(){
      System.out.println("吃吃吃");
   }
}

配置類: 
@Configuration  //設定為 配置類
@ComponentScan(basePackages = {"com.czxy.demo01"})   // 設定要掃描的包
@EnableAspectJAutoProxy // 設定 開啟切面  
public class SpringConfig01 {

}

切面類:
@Component
@Aspect  
public class MyAspect01 {

   @Before("execution(public void com.czxy.demo01.User.eat())")  
   public void bf01(){
      System.out.println("沐浴更衣 ");
   }
}

測驗類:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes ={SpringConfig01.class})
public class TestA {
   @Resource
   private User user;

   @Test
   public void test01(){
      user.eat();  
   }
}

執行結果:

img

4.1.3 AOP作用和優勢

l 作用:

\4. 在程式運行期間,不修改原始碼對已有方法進行增強,

l 優勢:

\5. 減少重復代碼

\6. 提高開發效率

\7. 維護方便

4.1.4 快速入門2

需求: 使用AOP 對UserService介面的兩個方法進行增強. 在方法執行之前,開啟事務,在方法執行之后關閉事務.

專案結構:

img

具體代碼:

Pom中需要添加aop相關的依賴

img

UserService介面: 介面中提供兩個方法

public interface UserService {

   public void addUser();

   public void delUser();

}

實作類UserServiceImpl

@Service  
public class UserServiceImpl implements UserService {

   @Override
   public void addUser() {
      System.out.println("添加用戶 ");
   }

   @Override
   public void delUser() {
      System.out.println("洗掉用戶");
   }
}

配置類:
@Configuration 
@ComponentScan(basePackages = "com.czxy.demo02") 
@EnableAspectJAutoProxy 
public class SpringConfiguration2 {
}

切面類MyAspect02:
@Component  
@Aspect  
public class MyAspact02 {

   @Before("execution(public void com.czxy.demo02.UserService.*())")  
   public void bf(){
      System.out.println("開啟事務");
   }

   @After("execution(public void com.czxy.demo02.UserService.*())") 
   public void af(){
      System.out.println("關閉事務");
   }
}


測驗類:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfiguration2.class)
public class TestB {

   @Resource  
   private UserService userService;

   @Test
   public void test01(){
      userService.addUser();  

      System.out.println("----------");

      userService.delUser();
   }
}

測驗結果:

img

4.1.5 快速入門3

需求: 使用AOP 對UserService和BookService介面的方法進行增強.

img

4.1.6 AOP實作方法

Spring AOP 主要通過2種代理技術來實作:動態代理、CGLIB

? 動態代理:用于對介面+實作類情況進行代理,

@EnableAspectJAutoProxy(proxyTargetClass = false )

? CGLIB:用于對僅有類情況進行代理,

@EnableAspectJAutoProxy(proxyTargetClass = true )

4.2 相關AOP術語

Target( *目標物件 *):

? 代理的目標物件,通俗點講:你需要增強的類,這個類就是目標物件

? 例如:UserServiceImpl

Joinpoint( *連接點 *):

? 所謂連接點是指可能被增強的位置,在spring中,AOP是對方法進行增強,這個位置/時機可以是方法前或者方法后,或者出例外的時候,

? 例如:addUser()方法執行之前的位置 或者 addUser()方法執行之后的位置 或者 AddUser出例外的時候

Pointcut( *切入點 *):

? 所謂切入點是指我們要對哪些Joinpoint進行攔截的定義,通俗講: 確定了在哪個位置進行增強

? 例如:@Before(“execution(public void com.czxy.demo02.UserService.addUser())”)

Advice( *通知 */ *增強 *): 具體要干的事情

? 所謂通知是指攔截到Joinpoint之后所要做的事情就是通知,

? 通知的型別:前置通知,后置通知,例外通知,最終通知,環繞通知,

? 例如:bf()、af()

Aspect( *切面 *):

? 是切入點和通知的結合,

? 例如:MyAspect類

Proxy *(代理) *:

? 一個類被AOP增強后,就產生一個結果代理類,

img

img

4.3 相關注解

注解描述
@Aspect把當前類宣告成切面類
@Before把當前方法看成是前置通知
@AfterReturning把當前方法看成是后置通知,
@AfterThrowing把當前方法看成是例外通知
@After把當前方法看成是最終通知
@Around把當前方法看成是環繞通知
@Pointcut指定切入點運算式

4.3.1 切入點運算式

execution:
		匹配方法的執行(常用)		
		execution(運算式)
運算式語法:execution([修飾符] 回傳值型別 包名.類名.方法名(引數))
寫法說明:
	全匹配方式:
		public void com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
	訪問修飾符可以省略	
		void com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
	回傳值可以使用*號,表示任意回傳值
		* com.itheima.service.impl.CustomerServiceImpl.saveCustomer()
	包名可以使用*號,表示任意包,但是有幾級包,需要寫幾個*
		* *.*.*.*.CustomerServiceImpl.saveCustomer()
	使用..來表示當前包,及其子包
		* com..CustomerServiceImpl.saveCustomer()
	類名可以使用*號,表示任意類
		* com..*.saveCustomer()
	方法名可以使用*號,表示任意方法
		* com..*.*()
	引數串列可以使用*,表示引數可以是任意資料型別,但是必須有引數
		* com..*.*(*)
	引數串列可以使用..表示有無引數均可,有引數可以是任意型別
		* com..*.*(..)
	全通配方式:
		* *..*.*(..)

4.3.2 通知方法

l 方式1:沒有引數形式

@Before("execution(public void com.czxy.demo01.User.eat())")
public void bf01(){
   System.out.println("洗手 ");
}

執行效果:

img

l 方式2:獲得引數JoinPoint,從而獲得目標類,目標方法等資訊

@Before("execution(public void com.czxy.demo01.User.eat())")
public void bf01(JoinPoint jp){ 
   System.out.println("洗手 ");

   System.out.println("目標類:"+jp.getTarget());//獲取目標類
   System.out.println("切入點:"+jp.getSignature());//獲取切入點
}

執行效果:

img

l 方式3:環繞通知獲得引數ProceedingJoinPoint,對目標方法的執行進行控制,

@Around("execution(public void com.czxy.demo01.User.eat())")
public void ar(ProceedingJoinPoint  jp) throws Throwable {
   System.out.println("洗手 ");

   jp.proceed();//執行 eat方法

   System.out.println("擦嘴");
}

執行效果:

img

4.3.3 抽取公共 切入點

使用@PointCut可以將公共的切入點進行抽取,一般都宣告在私有方法上,

在通知注解使用,通過方法名參考,

	@Pointcut("execution(* com.czxy.service..*.*(..))")
	private void myPointcut(){
		
	}
	
	@Before("myPointcut()")
	public void bf(JoinPoint joinPoint){
		System.out.println("前置..." + joinPoint.getTarget());
		System.out.println("前置..." + joinPoint.getSignature().getName());
	}
	
	@AfterReturning("myPointcut()")
	public void af(){
		System.out.println("后置...");
	}

4.4 完整通知演示

4.4.1 AOP編程

l 撰寫需要對目標類,增量的類和方法(可以復制)

	@Pointcut("execution(* com.czxy.service..*.*(..))")
	private void myPointcut(){
		
	}
	
	@Before("myPointcut()")
	public void bf(JoinPoint joinPoint){
		System.out.println("前置..." + joinPoint.getTarget());
		System.out.println("前置..." + joinPoint.getSignature().getName());
	}
	
	@AfterReturning("myPointcut()")
	public void af(){
		System.out.println("后置...");
	}

l 測驗

? img

4.4.2 目標介面和類

?介面
public interface UserService {
	
	public void saveUser();
	
	public String updateUser();

}

?實作類
@Service
public class UserServiceImpl implements UserService {

	@Override
	public void saveUser() {
		System.out.println("save");
	}

	@Override
	public String updateUser() {
		System.out.println("update");
		return "abc";
	}

}
4.4.3配置類
@ComponentScan(basePackages={"com.czxy"})
@EnableAspectJAutoProxy
public class SpringConfigruation {

}

4.4.4切面類
@Component
@Aspect
public class MyAspect2 {
	
	@Pointcut("execution(* com.czxy.service..*.*(..))") 
	private void myPointcut(){
		
	}
	
	@Before("myPointcut()")
	public void bf(JoinPoint joinPoint){
		System.out.println("前置..." + joinPoint.getTarget());
		System.out.println("前置..." + joinPoint.getSignature().getName());
	}
	
	@AfterReturning(value="myPointcut()",returning="ret") 
	public void ar(JoinPoint joinPoint , Object ret){ 
		System.out.println("后置..." + ret);
	}
	
	@Around("myPointcut()")
	public void ar(ProceedingJoinPoint joinPoint) throws Throwable{
		System.out.println("環繞前");
		
		joinPoint.proceed();	//執行目標方法
		
		System.out.println("環繞后");
	}
	
	@AfterThrowing(value="myPointcut()",throwing="ex") 
	public void at(JoinPoint joinPoint ,Throwable ex){ 
		System.out.println("例外:" + ex.getMessage());
	}
	
	@After("myPointcut()")
	public void af(){
		System.out.println("最終");
	}

}


4.4.5測驗類
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={SpringConfigruation.class})
public class UserDaoTest {
	
	@Resource
	private UserService userService;
	
	@Test
	public void testFindAll() throws SQLException{
		userService.saveUser();
		int i = 1/0;
		userService.updateUser();
	}
}

5. 整合MyBatis

之前使用的持久層框架是MyBatis, 現在將Mybatis框架整合到Spring框架中,由Spring統一管理.其核心思路是把Mapper對應的實作類物件存放在IOC容器中.

需求:

通過Spring+Mybatis整合,把一個用戶的資訊添加到資料庫中.

實作步驟:

  1. 環境搭建

  2. 撰寫Dao和Service

  3. 書寫配置類

  4. 測驗

完整的專案結構如下:

img

5.1 環境搭建

5.1.1 匯入 pom相關的依賴

<properties>
  <spring.version>4.2.4.RELEASE</spring.version>
</properties>


<dependencies>

  <!-- spring start -->

  <!--spring core start-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring core end-->

  <!--spring aop start-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spirng aop end-->

  <!--spring aspects start-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring aspects end-->

  <!--spring instrumentation start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-instrument</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring instrumentation end-->

  <!--spring messaging start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring messaging end-->

  <!--spring data access start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-oxm</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jms</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring data access end-->

  <!--spring web start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>


  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc-portlet</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring web end -->

  <!--spring test start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
  </dependency>

  <!--spring test end -->
  <!-- spring end -->


  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper</artifactId>
    <version>3.5.2</version>
  </dependency>
  <dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>3.7.5</version>
  </dependency>
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
  </dependency>

  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
  </dependency>
  <dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>1.3.2</version>
  </dependency>
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
  </dependency>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>compile</scope>
  </dependency>


</dependencies>

5.1.2 組態檔

img

jdbc.driver=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://127.0.0.1:3306/test1

jdbc.username=root

jdbc.password=1234

5.1.3 創建資料庫和表

CREATE TABLE USER(
 uid VARCHAR(32) PRIMARY KEY,
 username VARCHAR(50),
 PASSWORD VARCHAR(32)
)

5.1.4 創建domain

img

public class User {
    @Id
    private String uid;
    private String username;
    private String password;
     //getter和setter方法
     //....
}

5.2 撰寫dao和service

5.2.1 撰寫dao介面

img

package com.czxy.dao;

import com.czxy.domain.User;
import tk.mybatis.mapper.common.Mapper;

public interface UserMapper extends Mapper<User> {
}

5.2.2 撰寫service介面

img

package com.czxy.service;

import com.czxy.domain.User;

public interface UserService {

   public User findByPrimaryKey(String uid);

   public void insertUser(User user);


}

5.2.3 撰寫Service實作類

img

package com.czxy.service.impl;


import com.czxy.dao.UserMapper;
import com.czxy.domain.User;
import com.czxy.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

@Service
@Transactional  
public class UserServiceImpl implements UserService {

   @Resource
   private UserMapper userMapper;

   @Override
   public User findByPrimaryKey(String uid) {
      return userMapper.selectByPrimaryKey(uid);
   }

   @Override
   public void insertUser(User user) {

      userMapper.insert(user);

   }
}

5.3 配置類

5.3.1 spring配置類

1.配置注解

? 1.1 掃描注解包

? 1.2加載properties檔案

? 1.3 開啟注解事務支持

2.獲得properties資料(實作類、@Value)

3.配置資料源DataSource

4.配置事務管理器(DataSourceTransactionManager)

package com.czxy.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

import javax.annotation.Resource;
import javax.sql.DataSource;

@Configuration
@ComponentScan(basePackages = {"com.czxy"})
@EnableTransactionManagement
@PropertySource(value = "classpath:db.properties")
public class SpringConfig {

   // 4.2.4版本 固定配置
   @Bean
   public static PropertySourcesPlaceholderConfigurer create(){
      return  new PropertySourcesPlaceholderConfigurer();
   }

   //讀取資料庫相關配置
   @Value("${jdbc.driver}")
   private String driverClass;
   @Value("${jdbc.url}")
   private String url;
   @Value("${jdbc.username}")
   private String username;
   @Value("${jdbc.password}")
   private String password;


   //資料源使用德魯伊連接池
   @Bean
   public DataSource dataSource(){
      DruidDataSource ds = new DruidDataSource();
      ds.setDriverClassName(driverClass);
      ds.setUrl(url);
      ds.setUsername(username);
      ds.setPassword(password);
      return ds;
   }

   // 開啟事務管理器
   @Bean
   @Resource
   public DataSourceTransactionManager txManager(DataSource dataSource){
      return  new DataSourceTransactionManager(dataSource);
   }


}

5.3.2 mybatis配置類【新內容】

如下代碼直接當做配置類拷貝即可.

1.配置session工廠,spring和MyBatis整合時,通過SqlSessionFactoryBean獲得SqlSessionFactory

? SqlSessionFactoryBean只能加載mapper映射檔案

? 注解開發需要加載Mapper類,故需要對mapper進行掃描

2.配置映射掃描器

package com.czxy.config;

import com.github.pagehelper.PageHelper;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Properties;

/💃
 * Spring整合MyBatis的配置類
 * @author Administrator
 */
// 宣告
@Configuration
public class MyBatisConfig {
   
   /💃
    * 構建SessionFactory物件,SessionFactory可以創建Session物件,最后使用Session操作資料庫
    * @param dataSource
    * @return
    * @throws Exception
    */
   @Bean
   @Resource
   public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
      // 1.通過工廠bean創建物件,最后需要呼叫 getObject()獲得具體的物件
      SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
      // 1.1 設定資料源
      factoryBean.setDataSource(dataSource);
      // 1.2 設定別名包掃描
      factoryBean.setTypeAliasesPackage("com.czxy.domain");
      // 1.3 全域配置:駝峰映射
      org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
      config.setMapUnderscoreToCamelCase(true);
      factoryBean.setConfiguration(config);
      
      // 2 插件配置
      // 2.1 分頁插件
      PageHelper pageHelper = new PageHelper();
      Properties pageProps = new Properties();
      pageProps.setProperty("dialect", "mysql");
      pageProps.setProperty("rowBoundsWithCount", "true");
      pageHelper.setProperties(pageProps);
      factoryBean.setPlugins(new Interceptor[] { pageHelper });
      
      // 3 通過工廠bean獲得 sqlSessionFactory
      return factoryBean.getObject();
   }
   
   /💃
    * 掃描Dao的包,查找各種XxxMapper介面,創建好UserMapper等物件存入到IOC的容器中
    * @return
    */
   @Bean
   public MapperScannerConfigurer mapperScanner() {
      MapperScannerConfigurer configurer = new MapperScannerConfigurer();
      configurer.setBasePackage("com.czxy.dao");
      return configurer;
   }
   
}

5.4 測驗類

5.4.1 方式1:整合Junit

package com.czxy.test;


import com.czxy.config.MyBatisConfig;
import com.czxy.config.SpringConfig;
import com.czxy.domain.User;
import com.czxy.service.UserService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfig.class,MyBatisConfig.class})
public class TestA {


   @Resource
   private UserService userService;

   @Test
   public void test01(){
      User user = new User("u001","張三豐","123");

      userService.insertUser(user);

      System.out.println("添加完畢");
   }
}

測驗結果: 成功添加用戶資訊

img

img

5.4.2 方式2:手動創建工廠

public class TestB {

   public static void main(String[] args) {

      //1.創建工廠,設定兩個配置類
      ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class,MyBatisConfig.class);
      //2.從工廠獲取需要的物件
      UserService userService = applicationContext.getBean(UserService.class);
      //3.執行陳述句

      User user = new User("u800","zhangsan","123");

      userService.insertUser(user);

      System.out.println("添加完畢");
   }

}

5.4.3 完整的UserService

userService:
public interface UserService {
    void addUser(User user);
    void updateUser(User user);
    void delUser(String uid);
    User findByPrimaryKey(String uid);
    List<User> findAll();
    List<User> findByPage();
}



userServiceImpl:

@Service
@Transactional // 第五節講解
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    public void addUser(User user) {
         userMapper.insert(user);
    }

    public void updateUser(User user) {
        userMapper.updateByPrimaryKey(user);
    }

    public void delUser(String uid) {
        userMapper.deleteByPrimaryKey(uid);
    }

    public User findByPrimaryKey(String uid) {
        return userMapper.selectByPrimaryKey(uid);
    }

    public List<User> findAll() {
        return userMapper.selectAll();
    }

    public List<User> findByPage() {
        // PageHelper
        // 第一個引數:第幾頁
        // 第二個引數:獲取條數 ,PageHelper這個代碼后的第一個sql陳述句進行分頁
        PageHelper.startPage(1, 2);

        // 查找
//        userMapper.selectAll();
        List<User> list = userMapper.select(null);

        // 封裝到pageInfo
        PageInfo<User> info = new PageInfo<User>(list);
        return info.getList();
    }
}

1 什么是Spring

2 什么是IOC

3 什么是AOP

在不改變原代碼的情況下,對已有功能進行增強

目標物件

連接點

切入點

通知/增強(前置通知、后置通知、環繞通知…)

切面

代理

4 常用注解

IOC:

@Component

@Repository

@Service

@Controller

@Resource

@Autowired

@Bean

? @RunWith

? @ContextConfiguration

? @Configuration

AOP:@After @Before @AfterReturning @AfterThrowing @Around @Joinpoint

6. 事務管理

6.1 案例:轉賬

6.1.1 需求描述:

完成轉賬功能, 根據兩個賬戶的id和要轉賬的錢money,對其中一個id的錢-money,對另一個id的錢+money.

分析:

轉賬功能 需要由兩個動作完成.

  1. 賬戶1減錢

  2. 賬戶2加錢

減錢:根據賬戶id對錢數 減

加錢:根據賬戶id 對錢數 加

總體思路:

\1. SM整合環境搭建好.

\2. 在service中提供轉賬功能.

\3. 測驗類中測驗.轉賬功能

專案結構如下:

img

6.1.2 環境搭建

l 步驟1:匯入jar包坐標

l 步驟2:組態檔

img

l 步驟3:資料庫和表

CREATE TABLE account(

 id INT PRIMARY KEY AUTO_INCREMENT,

 NAME VARCHAR(40),

 money FLOAT

);

INSERT INTO account(NAME,money) VALUES('jack',10);

INSERT INTO account(NAME,money) VALUES('rose',10);

6.1.3 撰寫domain

public class Account {
    @Id
    private Integer id;
    private String name;
    private Double money;
    //省略getter和setter方法	
}

6.1.4 撰寫dao

public interface AccountMapper extends Mapper<Account> {

}

6.1.5 撰寫service

AccountService介面:

public interface AccountService {
    public void change(Integer inId,Integer outId,Double money);
}

AccountServiceImpl實作類:

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;


    public void change(Integer inId, Integer outId, Double money) {
//加錢
        Account account = accountMapper.selectByPrimaryKey(inId);
        account.setMoney(account.getMoney()+money);

        accountMapper.updateByPrimaryKey(account);


       //減錢
        Account account1 = accountMapper.selectByPrimaryKey(outId);
        account1.setMoney(account1.getMoney()-money);

        accountMapper.updateByPrimaryKey(account1);
    }
}

6.1.6 測驗

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringConfig.class,MyBatisConfig.class})
public class TestA {
   @Resource
   private AccountService accountService;

   @Test
   public void test01(){
      accountService.change(1,2,1d);
      System.out.println("完畢");
   }
}

測驗結果: 執行成功結果正確

img

修改Service中的代碼,繼續測驗:

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;


    public void change(Integer inId, Integer outId, Double money) {
        Account account = accountMapper.selectByPrimaryKey(inId);
        account.setMoney(account.getMoney()+money);

        accountMapper.updateByPrimaryKey(account);

        int i=1/0;

        Account account1 = accountMapper.selectByPrimaryKey(outId);
        account1.setMoney(account1.getMoney()-money);

        accountMapper.updateByPrimaryKey(account1);
    }
}

結果: 一個賬號加錢了, 一個賬號沒減錢

img

l 事務的概述

n 事務指的是邏輯上的一組操作,組成這組操作的各個單元要么全都成功,要么全都失敗.

n 事務作用:保證一組操作要么全都成功,對資料庫進行完整更新,要么在某一個動作失敗的時候讓資料恢復原狀,不會引起不完整的修改,

6.2 事務概述

? JavaEE體系進行分層開發,事務處理位于業務層,Spring提供了分層設計 業務層 的事務處理解決方案,

? spring的事務控制是基于AOP的,也就是spring提供了實作類對我們的業務方法進行增強,完成事務具體的操作,

6.3 Spring事務相關的術語

6.3.1 事務平臺管理器: PlatformTransactionManager

? spring通過事務管理器來管理事務,

? 事務管理器PlatformTransactionManager提供了事務需要的基本操作,

img

實作類描述
DataSourceTransactionManager使用JdbcTemplate或MyBatis需要的事務管理器

img

6.4 事務入門

6.4.1 修改配置類

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;


    public void change(Integer inId, Integer outId, Double money) {
        Account account = accountMapper.selectByPrimaryKey(inId);
        account.setMoney(account.getMoney()+money);

        accountMapper.updateByPrimaryKey(account);

        int i=1/0;

        Account account1 = accountMapper.selectByPrimaryKey(outId);
        account1.setMoney(account1.getMoney()-money);

        accountMapper.updateByPrimaryKey(account1);
    }
}

6.4.2 修改Service

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;


    public void change(Integer inId, Integer outId, Double money) {
        Account account = accountMapper.selectByPrimaryKey(inId);
        account.setMoney(account.getMoney()+money);

        accountMapper.updateByPrimaryKey(account);

        int i=1/0;

        Account account1 = accountMapper.selectByPrimaryKey(outId);
        account1.setMoney(account1.getMoney()-money);

        accountMapper.updateByPrimaryKey(account1);
    }
}

6.5 事務高級 ( 面試必背 )

6.5.1 事務特性:ACID

l 原子性(Atomicity)原子性是指事務是一個不可分割的作業單位,事務中的操作要么都成功,要么都失敗,

l 一致性(Consistency)事務前后資料的完整性必須保持一致,

l 隔離性(Isolation)事務的隔離性是指多個用戶并發訪問資料庫時,一個用戶的事務不能被其它用戶的事務干擾,多個并發事務之間資料要相互隔離,

l 持久性(Durability)持久性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響,

6.5.2 并發訪問問題

如果不考慮隔離性,事務存在并發訪問問題,

臟讀:讀未提交

不可重復度:讀已提交(update)兩次讀取的結果不一致

幻讀/虛讀:讀已提交(insert)兩次讀取的結果不一致

\1. 臟讀:(讀未提交)一個事務讀到了另一個事務未提交的資料.

img

\2. 不可重復讀(讀已提交):一個事務讀到了另一個事務已經提交(update)的資料,引發另一個事務,在事務中的多次查詢結果不一致,(要保證同一個事物的多次查詢同一個資料,結果一致)

img

\3. 虛讀 /幻讀:(讀已提交)一個事務讀到了另一個事務已經提交(insert)的資料,導致另一個事務,在事務中多次查詢的結果不一致,(資料量不同)

img

嚴重性: 臟讀 > 不可重復讀 >虛讀(幻讀)

6.5.3 隔離級別:解決問題

l 資料庫規范規定了4種隔離級別,分別用于描述兩個事務并發的所有情況,

\1. read uncommitted 讀未提交,一個事務讀到另一個事務沒有提交的資料,

a) 存在:3個問題(臟讀、不可重復讀、虛讀),

b) 解決:0個問題

效率最高,引發所有讀問題

基本不用

\2. read committed 讀已提交,一個事務讀到另一個事務已經提交的資料,

a) 存在:2個問題(不可重復讀、虛讀),

b) 解決:1個問題(臟讀)

如果要 效率,那么選擇這個read committed

\3. repeatable read :可重復讀,在一個事務中讀到的資料資訊始終保持一致,無論另一個事務是否提交,

a) 存在:1個問題(虛讀),

b) 解決:2個問題(臟讀、不可重復讀)

如果 要求安全,選擇這個repeatable read

虛讀的問題可以通程序式來規避:

  1. 事務剛開啟時,可以count(*)

  2. 事務要關閉時,可以count(*)

  3. 比對,如果兩次資料一致,說明沒有虛讀

\4. serializable 串行化,同時只能執行一個事務,相當于事務中的單執行緒,

a) 存在:0個問題,

b) 解決:1個問題(臟讀、不可重復讀、虛讀)

效率最低,安全性最高,基本不用

l 安全和性能對比

n 安全性:serializable > repeatable read > read committed > read uncommitted

n 性能 : serializable < repeatable read < read committed < read uncommitted

l 常見資料庫的默認隔離級別:

n MySql:repeatable read 安全,本身做的優化比較好

n Oracle:read committed 效率

6.5.4 術語

事務:

img

TransactionDefinition:事務的定義資訊物件,需要知道,方便知道事務有哪些設定項,

TransactionStatus:事務的狀態物件,spring內部使用的物件,不需要關注,

6.5.5 定義物件:概述 TransactionDefinition

img

通過分析事務定義資訊物件,spring事務定義主要涉及以下4方面:隔離級別、傳播行為、超時、只讀

6.5.6 定義物件:只讀

開發中,查詢資料,不會伴隨增刪改,所以建議查詢時設定為只讀,

注解描述
@Transactional(readOnly=true)只讀事務,DQL使用
@Transactional(readOnly=false)默認值,不是只讀事務,可以進行增刪改操作,DML使用

6.5.7 定義物件:超時

默認值是-1,沒有超時限制,如果有,以秒為單位進行設定,(一般不設定)

注解描述
@Transactional(timeout=60)設定超時為60秒,如果還沒有操作結束,將拋例外,

6.5.8 定義物件:隔離級別

事務隔離級別反映事務提交并發訪問時的處理態度,

注解描述
@Transactional(isolation=Isolation.DEFAULT)默認級別
@Transactional(isolation=Isolation.READ_UNCOMMITTED)讀未提交
@Transactional(isolation=Isolation.READ_COMMITTED)讀已提交 oracle
@Transactional(isolation=Isolation.REPEATABLE_READ)可重復讀 mysql
@Transactional(isolation=Isolation.SERIALIZABLE)串行化

img

6.5.9 定義物件:傳播行為 ( Spring特有 )

傳播行為:業務A使用了業務B,AB之間事務共享問題,就是事務的傳播行為,

spring中事務的傳播行為共7種,

注解描述
@Transactional(propagation=Propagation.REQUIRED)默認值,支持當前事務,如果當前沒有事務,就新建一個事務
@Transactional(propagation=Propagation.SUPPORTS)支持當前事務,如果當前沒有事務,就以非事務方式執行
@Transactional(propagation=Propagation.MANDATORY)支持當前事務,如果當前沒有事務,就拋出例外
@Transactional(propagation=Propagation.REQUIRES_NEW)新建事務,如果當前存在事務,把當前事務掛起
@Transactional(propagation=Propagation.NOT_SUPPORTED)以非事務方式執行操作,如果當前存在事務,就把當前事務掛起
@Transactional(propagation=Propagation.NEVER)以非事務方式執行,如果當前存在事務,則拋出例外
@Transactional(propagation=Propagation.NESTED)如果當前存在事務,則在嵌套事務內執行,如果當前沒有事務,則執行REQUIRED類似的操作

7. 附錄

Pom01-Spring入門

<properties>

  <spring.version>4.2.4.RELEASE</spring.version>

</properties>


 <!-- spring start -->

  <!--spring core start-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
  </dependency>
 <!--spring core end-->

  <!--spring aop start-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spirng aop end-->

  <!--spring aspects start-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring aspects end-->

  <!--spring instrumentation start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-instrument</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring instrumentation end-->

  <!--spring messaging start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring messaging end-->

  <!--spring data access start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-oxm</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jms</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring data access end-->

  <!--spring web start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>


<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc-portlet</artifactId>
  <version>${spring.version}</version>
</dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
   <!--spring web end -->

  <!--spring test start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring test end -->
  <!-- spring end -->
rsion>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context-support</artifactId>
    <version>${spring.version}</version>
  </dependency>
 <!--spring core end-->

  <!--spring aop start-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spirng aop end-->

  <!--spring aspects start-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring aspects end-->

  <!--spring instrumentation start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-instrument</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring instrumentation end-->

  <!--spring messaging start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-messaging</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring messaging end-->

  <!--spring data access start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-oxm</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jms</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring data access end-->

  <!--spring web start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>${spring.version}</version>
  </dependency>


<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc-portlet</artifactId>
  <version>${spring.version}</version>
</dependency>

  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>${spring.version}</version>
  </dependency>
   <!--spring web end -->

  <!--spring test start -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
  </dependency>
  <!--spring test end -->
  <!-- spring end -->

后記
📢博客主頁:https://manor.blog.csdn.net
📢歡迎點贊 👍 收藏 ?留言 📝 如有錯誤敬請指正!
📢本文由 manor 原創,首發于 CSDN博客🙉
📢Hadoop系列文章會每天更新!?

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/305671.html

標籤:java

上一篇:IDEA遠程部署除錯Java應用程式

下一篇:【Java】瘋狂作圖之剖釋String類之媽見夸之作

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more