【Mybatis + Spring】 Mybatis - Spring 结合
环境搭建 EvBuild
软件环境准备
- MySQL 5.0 +
- IDEA 2018 +
- JDK1.8 +
依赖包相关
- Junit单元测试
- JDBC驱动
- Mybatis 组件
- Spring组件
- AopWeaver切面织入包
- Mybatis-Spring【MS专用整合包】
- Lombok
- Log4J 日志输出
官方文档:
http://mybatis.org/spring/zh/index.html
什么是 MyBatis-Spring?
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。
它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,
以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。
最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
使用须知:
使用 MyBatis-Spring 之前,你需要先熟悉 Spring 和 MyBatis 这两个框架和有关它们的术语。
这很重要——因为本手册中不会提供二者的基本内容,安装和配置教程。
MyBatis-Spring 需要以下版本:
MyBatis-Spring | MyBatis | Spring 框架 | Spring Batch | Java |
---|---|---|---|---|
2.0 | 3.5+ | 5.0+ | 4.0+ | Java 8+ |
1.3 | 3.4+ | 3.2.2+ | 2.1+ | Java 6+ |
工程创建
在前面的Spring工程基础上创建新模块
开始配置Maven依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.4</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency> <!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency> <!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
资源过滤问题
<!--在build中配置resources,来防止我们资源导出失败的问题-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource> <resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
回顾原生Mybatis开发步骤:
1、编写实体类
2、Mybatis-Config.xml核心配置文件
3、Dao接口,或者说Mapper接口
4、编写Mapper.xml映射器配置、注册映射器
5、测试
实体类POJO
package cn.dai.pojo; import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor; @Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer user_id;
private String user_name;
private String user_password;
}
Mybatis-Config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration> <settings>
<setting name="logImpl" value="LOG4J"/>
</settings> <typeAliases>
<package name="cn.dai.pojo"/>
</typeAliases> <environments default="dev1"> <environment id="dev1">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments> <mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
</configuration>
Mapper.xml
很多人不喜欢映射器文件和接口放在一起,并且Maven也确实存在资源过滤问题
这样,我们可以放在资源目录下,新建一个mappers目录,统一放在这里面
编写映射器UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.dai.mapper.UserMapper"> <select id="getAllUserList" resultType="user">
SELECT * FROM user;
</select> </mapper>
在核心配置中这样注册映射器
<mappers>
<mapper resource="mappers/UserMapper.xml"/>
</mappers>
MybatisUtil.java
我们自己配置的会话获取工具类
public class MybatisUtil {
private static SqlSessionFactory sqlSessionFactory; static {
String mybatis_config = "Mybatis-Config.xml"; try {
InputStream inputStream = Resources.getResourceAsStream(mybatis_config); SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); sqlSessionFactoryBuilder = null;
} catch (IOException e) {
e.printStackTrace();
}
} public static SqlSession getSqlSession(boolean closeTransaction) {
return sqlSessionFactory.openSession(closeTransaction);
}
}
配置LOG4J日志输出【可选】
如果不要配置,把Mybatis-Config.xml的Settings删除
编写log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file #控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n #文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/l4j.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n #日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
在测试类加入日志实例
org.apache.log4j.Logger;
private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(MybatisTest.class);
测试Mybatis环境搭建是否正常
public class MybatisTest { private static org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(MybatisTest.class); @Test
public void sqlTest(){
SqlSession sqlSession = MybatisUtil.getSqlSession(true);
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> allUserList = mapper.getAllUserList(); for (User user:allUserList){
logger.info(user);
} sqlSession.close();
}
}
开始整合 Start Integration
现在我们把对象交给Spring管理,
再也不需要我们自己编写的MybatisUtil会话获取工具类了
编写Spring的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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c" 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 http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
"
>
<context:annotation-config />
<context:component-scan base-package="cn.dai" />
<aop:aspectj-autoproxy proxy-target-class="false"/> </beans>
快速上手
要和 Spring 一起使用 MyBatis,需要在 Spring 应用上下文中定义至少两样东西:
一个 SqlSessionFactory 和至少一个数据映射器类。
在 MyBatis-Spring 中,可使用 SqlSessionFactoryBean来创建 SqlSessionFactory。
要配置这个工厂 bean,只需要把下面代码放在 Spring 的 XML 配置文件中:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
或者使用纯JavaConfig的注解方式
@Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource());
return factoryBean.getObject();
}
注意:SqlSessionFactory 需要一个 DataSource(数据源)。
这可以是任意的 DataSource,只需要和配置其它 Spring 数据库连接一样配置它就可以了。
【在狂神的是XML配置,上面的会话工厂Bean需要引用一个数据源实例,它采用的是Spring提供的数据源】
<!-- 我们所学过的连接池【数据源】有C3P0、DRUID、HIKARI、DBCP、 -->
<!-- 这里使用Spring提供的连接池-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///mybatis?serverTimezone=GMT" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
可以看看这个数据源类的源码是怎样的?
源码:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package org.springframework.jdbc.datasource; import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils; public class DriverManagerDataSource extends AbstractDriverBasedDataSource {
public DriverManagerDataSource() {
} public DriverManagerDataSource(String url) {
this.setUrl(url);
} public DriverManagerDataSource(String url, String username, String password) {
this.setUrl(url);
this.setUsername(username);
this.setPassword(password);
} public DriverManagerDataSource(String url, Properties conProps) {
this.setUrl(url);
this.setConnectionProperties(conProps);
} public void setDriverClassName(String driverClassName) {
Assert.hasText(driverClassName, "Property 'driverClassName' must not be empty");
String driverClassNameToUse = driverClassName.trim(); try {
Class.forName(driverClassNameToUse, true, ClassUtils.getDefaultClassLoader());
} catch (ClassNotFoundException var4) {
throw new IllegalStateException("Could not load JDBC driver class [" + driverClassNameToUse + "]", var4);
} if (this.logger.isDebugEnabled()) {
this.logger.debug("Loaded JDBC driver: " + driverClassNameToUse);
} } protected Connection getConnectionFromDriver(Properties props) throws SQLException {
String url = this.getUrl();
Assert.state(url != null, "'url' not set");
if (this.logger.isDebugEnabled()) {
this.logger.debug("Creating new JDBC DriverManager Connection to [" + url + "]");
} return this.getConnectionFromDriverManager(url, props);
} protected Connection getConnectionFromDriverManager(String url, Properties props) throws SQLException {
return DriverManager.getConnection(url, props);
}
}
所以,在Mybatis-Config.xml的环境配置就可以舍弃了
Mybatis-Config.xml可以删除的部分
<environments default="dev1"> <environment id="dev1">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
连接参数的读取就可以让Spring的ApplicationContext读取了
接着,Mybatis-Config.xml这个核心配置文件又
可以让会话工厂实例的configuration属性读取
<!-- SQL会话工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configuration" value="classpath:Mybatis-Config.xml" />
</bean>
其实这个会话工厂实例Bean的设置完全涵盖了核心配置
【狂神推荐 别名 & 设置 留给 Mybatis-Config.xml 核心配置,其他部分完全Spring容器接管】
注意映射器的配置只能保存一个,在Spring写了就不能再在Mybatis-Config.xml保留
<!-- SQL会话工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据源 连接池-->
<property name="dataSource" ref="dataSource" />
<!-- 核心配置地址 -->
<property name="configLocation" value="classpath:Mybatis-Config.xml" />
<!-- 配置映射器位置-->
<property name="mapperLocations" value="classpath:mappers/UserMapper.xml"/>
</bean>
然后是SqlSession的Bean注册
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<!-- 只允许构造器注入 没有setSqlSession方法 -->
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
但是在Mapper包,我们就需要多写一个实现类
public class UserMapperImpl implements UserMapper{ // 现在使用SqlSessionTemplate完成
SqlSessionTemplate sqlSession; public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
} public List<User> getAllUserList() {
return sqlSession.getMapper(UserMapper.class).getAllUserList();
}
}
Bean注册
<bean id="userMapperImpl" class="cn.dai.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSessionTemplate" />
</bean>
测试
import cn.dai.mapper.UserMapper;
import cn.dai.pojo.User;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; public class MybatisSpringIntegration { private static Logger logger = Logger.getLogger(MybatisSpringIntegration.class); @Test
public void msTest(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Canned.xml");
UserMapper userMapper = applicationContext.getBean("userMapperImpl", UserMapper.class); List<User> allUserList = userMapper.getAllUserList(); for (User user:allUserList){
logger.info(user);
} }
}
整合总结:
1、数据库数据准备
2、实体类编写,暂不需要Bean注册
3、编写Mybatis-Config.xml配置,也可以让Spring全权Bean化处理
4、编写Mapper接口,SQL的抽象方法
5、编写Mapper.xml映射器配置,可以放在接口包,也可以是资源目录
6、Mapper的注册交给Mybatis-Config.xml或者是Bean处理
7、LOG4J日志输出配置【可选】
8、配置Spring容器类
9、配置数据源【DataSource 连接池】Bean化
10、配置SQL会话工厂【SqlSessionFactory】Bean化
11、SQL会话工厂可以完全配置Mybatis-Config.xml【可选,自己看情况设置】
12、配置SQL会话模板【SqlSessionTemplate】Bean化
13、编写XXXmapper实现类,同时配置Bean
14、测试,或者实际使用,从ApplicationContext获取即可
第二种整合方式:
只是在上面的基础上有一点改动
官方在我们编写实现类要组合SqlSessionTemplate的这个步骤上封装了
我们只需要继承SqlSessionDaoSupport类即可
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper { public List<User> getAllUserList() {
return this.getSqlSession().getMapper(UserMapper.class).getAllUserList();
}
}
在Bean的配置上,只需要注入SQL会话工厂即可
<bean id="userMapperImpl2" class="cn.dai.mapper.UserMapperImpl2">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
测试
@Test
public void msTest2(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Canned.xml");
UserMapper userMapper = applicationContext.getBean("userMapperImpl2", UserMapper.class);
List<User> allUserList = userMapper.getAllUserList();
for (User user:allUserList){
logger.info(user);
}
}
关于Spring的声明式事务
约束声明
xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
事务配置
<!--https://blog.csdn.net/jiadajing267/article/details/81056057-->
<!-- 配置声明式事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean> <!-- 2. 配置事务属性 -->
<!--<tx:advice>元素声明事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 根据方法名指定事务的属性 -->
<tx:method name="*"/>
<!--propagation配置事务传播行为-->
<tx:method name="purchase" propagation="REQUIRES_NEW"/>
<!--isolation配置事务的隔离级别-->
<tx:method name="update*" isolation="SERIALIZABLE"/>
<!--rollback-for配置事务遇到异常必须回滚,no-rollback-for配置事务遇到异常必须不能回滚-->
<tx:method name="add*" rollback-for="java.io.IOException" no-rollback-for="com.dmsd.spring.tx.BookStockException"/>
<!--read-only配置事务只读属性-->
<tx:method name="find*" read-only="true"/>
<!--timeout配置事务的超时属性-->
<tx:method name="get*" timeout="3"/>
</tx:attributes>
</tx:advice> <!-- 3. 配置事务切入点, 以及把事务切入点和事务属性关联起来 -->
<aop:config>
<aop:pointcut expression="execution(* cn.dai.mapper.UserMapper.*.*(..))"
id="txPointCut"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
【Mybatis + Spring】 Mybatis - Spring 结合的更多相关文章
- SpringMVC + Spring + MyBatis 整合 + Spring shrio + easyUI + 权限管理框架,带shrio session和shrio cache集群实现方案
工作之余先来写了一个不算规范的简单架子 基于spring mvc + spring + mybatis + Spring shrio 基于redis的集群方案 系统权限部分,分成多个机构,其中每个机构 ...
- Idea SpringMVC+Spring+MyBatis+Maven调整【转】
Idea SpringMVC+Spring+MyBatis+Maven整合 创建项目 File-New Project 选中左侧的Maven,选中右侧上方的Create from archetyp ...
- SpringMVC+Spring+MyBatis+Maven调整【转】
Idea SpringMVC+Spring+MyBatis+Maven整合 创建项目 File-New Project 选中左侧的Maven,选中右侧上方的Create from archetyp ...
- struts2 spring mybatis 整合(test)
这几天搭了个spring+struts2+mybatis的架子,练练手,顺便熟悉熟悉struts2. 环境:myEclipse10+tomcat7+jdk1.6(1.8的jre报错,所以换成了1.6) ...
- Spring+Mybatis基于注解整合Redis
基于这段时间折腾redis遇到了各种问题,想着整理一下.本文主要介绍基于Spring+Mybatis以注解的形式整合Redis.废话少说,进入正题. 首先准备Redis,我下的是Windows版,下载 ...
- Spring+MyBatis框架中sql语句的书写,数据集的传递以及多表关联查询
在很多Java EE项目中,Spring+MyBatis框架经常被用到,项目搭建在这里不再赘述,现在要将的是如何在项目中书写,增删改查的语句,如何操作数据库,以及后台如何获取数据,如何进行关联查询,以 ...
- Maven+Spring MVC Spring Mybatis配置
环境: Eclipse Neon JDK1.8.0 Tomcat8.0 先决条件: Eclipse先用maven向导创建web工程.参见本站之前随笔. 本机安装完成mysql5:新建用户xuxy03设 ...
- SSM框架-----------SpringMVC+Spring+Mybatis框架整合详细教程
1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One ...
- 手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版)
手把手Maven搭建SpringMVC+Spring+MyBatis框架(超级详细版) SSM(Spring+SpringMVC+Mybatis),目前较为主流的企业级架构方案.标准的MVC设计模式, ...
- 3.springMVC+spring+Mybatis整合Demo(单表的增删该查,这里主要是贴代码,不多解释了)
前面给大家讲了整合的思路和整合的过程,在这里就不在提了,直接把springMVC+spring+Mybatis整合的实例代码(单表的增删改查)贴给大家: 首先是目录结构: 仔细看看这个目录结构:我不详 ...
随机推荐
- Linux下,安装单机版Flink
安装前准备 jdk环境 开始安装 下载安装包 地址1:https://archive.apache.org/dist/flink/flink-1.18.0/flink-1.18.0-bin-scala ...
- vue排行榜 加单位
- 燕千云 YQCloud 数智化业务服务平台 发布1.12版本
2022年4月29日,燕千云 YQCloud 数智化业务服务平台发布1.12版本,优化客户服务场景.深化智能预测服务的应用,加强系统在多渠道方面的集成,全面提升企业数智化服务的能力! 作为企业数字化服 ...
- Java反射获取字段的属性值及对比两个对象的属性值null差异赋值,递归算法查找
package com.example.demo; import java.lang.reflect.Field; /** * 需求描述:同一类的不同对象,如果某个字段的null则从另外的一个对象中赋 ...
- idea如何快速找到项目中待处理的TODO注释
idea如何快速找到项目中待处理的TODO注释 idea菜单栏 View -> Tool Windows,可以打开TODO窗口
- Filter过滤器进行统一参数处理demo
Filter过滤器进行统一参数处理demo import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet. ...
- Linux实时查看Java接口数据
1.Linux实时查看Java接口数据的方法 在Linux系统中实时查看Java接口数据通常涉及几个步骤: (1)编写Java应用程序:首先,我们需要有一个Java应用程序,它暴露了一个或多个HTTP ...
- k8s使用rbd作为存储
k8s使用rbd作为存储 如果需要使用rbd作为后端存储的话,需要先安装ceph-common 1. ceph集群创建rbd 需要提前在ceph集群上创建pool,然后创建image [root@ce ...
- Jenkins项目构建成功后,配置邮件
6.1 配置信息 6.1.1 发给多个收件人 邮件要发送给多个人,要使用[,]分割 6.1.2. 项目构建引用Editable Email Notification,设置tigger 在项目构建后,引 ...
- CLR via C# 笔记 -- 计算限制的异步操作(27)
1. 线程池基础. 创建和销毁线程是一个昂贵的操作,要耗费大量时间.太多的线程会浪费内存资源.由于操作系统必须调度可运行的线程并执行上下文切换,所以大多的线程还对性能不利.为了改善这个情况,CLR包含 ...