Spring
Spring简介
Spring—>春天;解决企业级快发的复杂性
2002,首次推出interface21框架Rod Johnson创始人,Spring基于interface21于2004年3yue24日推出。
Spring优点:
Spring是一个开源的免费的框架;Spring使一个轻量级的、非入侵的框架;控制反转(IOC)、面向切面编程(AOP);支持事务的处理,对框架整合的支持。
Spring Boot :
- 一个快速开发的脚手架
- 基于SpringBoot可以快速开发单个微服务
- 预定大于配置
Spring Cloud:
- SpringCloud是基于SpringBoot实现的。
Spring是分层java ee/se应用full-stack轻量级开源框架,以IOC((Inverse Of Control:控制反转)和AOP(Aspect Oriented Programming:⾯向切⾯编程)为内核,提供了展现层SpringMVC和持久层的SpringJDBC以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多的第三方框架和类库,逐渐称为只用最多的JavaEE企业级应用开源框架。
Spring优势
①方便解耦,简化开发:通过Spring提供的IOC容器,可以将对象空间的依赖关系交由Spring机型控制,避免硬编码所造成的过度耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
②AOP编程的支持:通过Spring的AOP功能,方便进行面向切面编程,许多不容易用传统的oop实现的功能可以通过AOP轻松应付。
③声明式事务支持:可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式⽅式灵活的进⾏事务的管理,提⾼开发效率和质量。
④方便程序测试:可以⾮容器依赖的编程⽅式进⾏⼏乎所有的测试⼯作,测试不再是昂贵的操作,⽽是随⼿可做的事情。
⑤⽅便集成各种优秀框架:Spring 可以降低各种框架的使⽤难度,提供了对各种优秀框架(SpringMVC、Mybatis、Hessian、Quartz 等)的直接⽀持。
⑥降低 JavaEE API 的使⽤难度:Spring 对 JavaEE API(如 JDBC、JavaMail、远程调⽤等)进⾏了薄薄的封装层,使这些API 的使⽤难度⼤为降低。
Spring的体系结构:
耦合:大白话就是代码模块之间的依赖关系,程序设计的目标就是:高内聚,低耦合
控制反转:面向对象设计原则之一,用来降低计算机代码之间的耦合度,最常见的方式叫做依赖注入(DI)。还有一种方式叫做“依赖查找”。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它,也被称作依赖注入。
SpringIOC解决程序耦合:
第一步:pom.xml文件中导入mysql的坐标
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
第二步:测试类中书写
/**************************方式1耦合度最高*************************/
// DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
// Connection root = DriverManager.getConnection("jdbc:mysql://localhost:3306/2307db?serverTimezone=GMT", "root", "123456");
// System.out.println(root);
注:new的方式是耦合度最高的,因为如果该类如果不存在的话直接改行代码报错。
/**************************方式2耦合度最一般*************************/
//使用反射
Class.forName("com.mysql.cj.jdbc.Driver");
Connection root = DriverManager.getConnection("jdbc:mysql://localhost:3306/2307db?serverTimezone=GMT", "root", "123456");
System.out.println(root);
注:使用反射的方式,来降低耦合度。
/**************************方式3耦合度最低*************************/
//创建工具类
Properties properties = new Properties();
//加载文件
InputStream inputStream = Test01.class.getClassLoader().getResourceAsStream("jdbc.properties");//propertise见下代码块
properties.load(inputStream);
//通过key获取value
String deiver = properties.getProperty("msg1");
String url = properties.getProperty("msg2");
String name = properties.getProperty("msg3");
String pwd = properties.getProperty("msg4");
Class.forName(deiver);
Connection root = DriverManager.getConnection(url, name, pwd);
System.out.println(root);
注:通过外部properties文件的方式降低耦合度。在修改数据库密码、用户名,库名时只需在properties文件中进行书写,解决硬编码问题。
msg1=com.mysql.cj.jdbc.Driver
msg2=jdbc:mysql://localhost:3306/2307db?serverTimezone=GMT
msg3=root
msg4=123456
Spring MVC 中使用工厂方法来降低耦合度:
在以往的视图层MVC三层中,往往是通过new 的方式进行调用的,service层创建dao层对象然后调用dao层的方法,在conrtoller中创建service层的对象,然后调用方法,上面我们提到过通过创建对象的方式耦合度最高下面进行改进。
第一步:pom文件中写坐标
略
第二步:创建MVC三层
略
第三步:创建一个BeansFactory
public class BeansFactory {
static Properties properties =null;
static {
try {
properties = new Properties();
InputStream inputStream = BeansFactory.class.getClassLoader().getResourceAsStream("beans.properties");//beans.properties见下面代码块
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static Object getBean(String key){
try {
String s = properties.getProperty(key);
Object o = Class.forName(s).newInstance();
return o;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
beans.properties
dao=com.li.dao.UserDaoImp
service=com.li.service.UserServiceImp
UserControllerImp(UserDaoImp、UserServiceImp类似)类
public class UserControllerImp implements IUserController{
// IUserService iUserService = new UserServiceImp();
IUserService iUserService = (IUserService)BeansFactory.getBean("service");
@Override
public void save() {
System.out.println("========controller的新增========");
iUserService.save();
}
}
测试类:
public class Test01 {
public static void main(String[] args) {
IUserController iUserController = new UserControllerImp();
iUserController.save();
}
}
SpringIOC
IOC控制反转:解耦,搭建IOC容器(spring容器),让容器解耦进行创建对象。
spring环境搭建:
1.添加坐标
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.29</version>
</dependency>
</dependencies>
2.添加主配置文件(resources中右键new->XML configuuration File -> spring config;先添加左边才能有spring config)
<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">
</beans>
spring IOC实现步骤:
1.创建JavaBean
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Student {
public String sname;
public int sage;
}
2.将JavaBean对象注入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">
<!--注入dao-->
<bean id="dao" class="com.li.dao.UserDaoImp"></bean>
</beans>
3.让springIOC容器以解耦方式实例化对象
3.1.加载spring容器获取核心对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(“beans.xml”);
3.2.获取实例
IUserDao dao = (IUserDao) applicationContext.getBean(“dao”);
dao.save();
public static void main(String[] args) {
//解耦获取dao对象
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
IUserDao dao = (IUserDao) applicationContext.getBean("dao");
dao.save();
}
关键字:
BeanFactory:父接口,多例模式
ApplicationContext:子接口,单例模式
ClassPathXmlApplicationContext========》通过相对路径加载主配置文件☆
FileSystemXmlApplicationContext=======》通过绝对路径加载主配置文件
AnnotationConfigApplicationContext====》通过相对路径加载配置类☆
SpringIOC:
IOC名词解释,作用是解耦,使用IOC容器管理项目组件之间的耦合关系是Spring框架的核心思想之一,主要用于解耦。IOC是指将创建对象的控制权转移给Spring框架进行管理。由Spring框架根据配置文件或注解等方式,创建bean对象并管理各个bean对象之间的依赖关系。使对象之间形成松散耦合的关系,实现解耦;
○ 控制 :指的是对象创建(实例化、管理)的权力
○ 反转 :控制权交给外部环境(Spring框架、IoC容器)
SpringDI
DI:依赖注入,是对IOC概念的不同角度的描述,是指应用程序在运行时,每一个bean对象都依赖IOC容器注入当前bean对象所需要的另外一个bean对象。(例如在MyBatis整合Spring时SqlSessionFactoryBean依赖IOC容器注入一个 DataSource数据源bean)
DI实现方式:
1.构造注入(通过构造方法进行粘合)
1.顾名思义就是通过构造器进行注入(以Service层)
public class UserServiceImp implements IUserService{
IUserDao dao;//声明
//创建构造器
public UserServiceImp(IUserDao dao) {
this.dao = dao;
}
@Override
public void save() {
System.out.println("========service的新增========");
//声明、创建构造器、在xml文件中注入后就等同于实例化了
dao.save();
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 构造注入 -->
<bean id="serviceImp" class="com.li.service.UserServiceImp">
<constructor-arg name="dao" ref="daoImp"></constructor-arg>
</bean>
<bean id="daoImp" class="com.li.dao.UserDaoImp"></bean>
</beans>
<!--====================完整的三层串联;java代码相同====================-->
<?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="controllerImp" class="com.li.controller.UserControllerImp">
<constructor-arg name="service" ref="serviceImp"></constructor-arg>
</bean>
<bean id="serviceImp" class="com.li.service.UserServiceImp">
<constructor-arg name="dao" ref="daoImp"></constructor-arg>
</bean>
<bean id="daoImp" class="com.li.dao.UserDaoImp"></bean>
</beans>
2.set注入(通过set方法进行粘合)
2.set顾名思义就是创建set方法;其实就是将构造器换成set方法,然后将xml文件中的constructor-arg换成property
public class UserServiceImp implements IUserService{
IUserDao dao;
public void setDao(IUserDao dao) {
this.dao = dao;
}
@Override
public void save() {
System.out.println("========service的新增========");
dao.save();
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--===================set注入(基本类型与String)======================-->
<bean id="student" class="com.li.common.Student">
<property name="sname" value="六六"></property>
<property name="sage" value="20"></property>
</bean>
<!--===================set注入(javaBean)=========================-->
<bean id="controllerImp" class="com.li.controller.UserControllerImp">
<property name="service" ref="serviceImp"></property>
</bean>
</beans>
2.1set注入的复杂类型略有不同,单独写
创建实体类
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Teacher {
public List myList;
public Set mySet;
public String[] myString;
public Map myMap;
public Properties myProp;
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--===================set注入(复杂类型)=========================-->
<bean id="teacher" class="com.li.common.Teacher">
<property name="myList">
<list>
<value>米饭</value>
<value>面条</value>
<value>馒头</value>
<value>香锅</value>
<value>麻辣烫</value>
</list>
</property>
<property name="myMap">
<map>
<entry key="华为Mate60Pro" value="8000"></entry>
<entry key="小米14pro" value="8000"></entry>
<entry key="苹果15pro" value="8000"></entry>
</map>
</property>
<property name="mySet">
<set>
<value>西瓜</value>
<value>葡萄</value>
<value>菠萝</value>
<value>哈密瓜</value>
</set>
</property>
<property name="myString">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
<value>5</value>
</array>
</property>
<property name="myProp">
<props>
<prop key="中国">陕西</prop>
<prop key="美国">华盛顿</prop>
<prop key="日本">大阪</prop>
<prop key="俄罗斯">红场</prop>
</props>
</property>
</bean>
</beans>
测试类:
public class Test02 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicaationContext.xml");
Teacher teacher = (Teacher)context.getBean("teacher");
System.out.println(teacher);
}
}
3.注解注入(通过注解实现粘合)============================================》后面讲
总结:
-
DI实现步骤: 1.思考,用什么方式?注入什么数据? 2.提供对应(构造,set)方法 public Student(String sname, int sage) { this.sname = sname; this.sage = sage; } 3.配置 <constructor-arg 属性名="属性值"></constructor-arg> 属性名: name=======>参数名 index======>参数索引 type=======>参数类型 value======>参数具体数据 ref========>参数数据的引用
SpringBean
springbean容器=bean的管理
一.spring对于bean实例化的管理
1.默认情况下调用类的无参构造方法进行
2.通过普通工厂进行对象的实例化
3.通过静态工厂进行对象的实例化
二.spring对于bean的作用域
含义:bean在spring容器中创建的策略以及访问的范围
编写位置:bean标签属性位置
编写语法:scope=“”
属性值:
singleton========>单例模式全局唯一性能好安全性低(默认方式)
prototype====>多例模式全局不唯一性能不好安全性高
以下作用域数据web模块=
request======>一次请求创建一个对象
session========>一个会话创建一个对象
三.spring对于bean的生命周期管理
单例模式:
实例化=====>容器创建的时候实例化
属性赋值(DI)
初始化=====>实例化完成,则自动初始化
InitializingBean类中的afterPropertiesSet
init-method属性绑定方法
使用操作
销毁======>容器关闭,所以的bean则自动销毁,销毁前会执行destroy-method=""方法,完成资源回收
四.spring管理bean的自动装配
手动注入:
<property name="service" ref="serviceImp"></property>
<constructor-arg></constructor-arg>
含义:将对象用DI的编程思想,自动注入给调用者(原先是手动)
编写位置:bean与beans标签的属性
编写语法:
autowire=“”》局部设置
default-autowire=“”》全局设置
编写属性:
byType==>按照类型自动装配 属性类型与bean的class一致(通过set注入实现)
byName==========>按照id属性自动装配 属性名称与bean的id一致(通过set注入实现)
constructor==========>按照类型自动装配 属性类型与bean的class一致(通过构造方法注入实现)
no==========>默认设置,无自动装配
编写注意:
1.按照类型装配,避免容器中有相同类型
2.按照名字装配,要保证需要的对象名在spring容器中有对应的id
3.可以同时进行全局与局部设置,就近原则
4.自动装配能简化代码配置,但是在大型项目中不推荐使用,可读性差
SpringAnnotation
spring的配置
1.spring2.5前==xml
2.spring2.5后==xml+annotation
3.spring3.0后==annotation+javaConfig配置类
spring2.5后=xml+annotation
目的 优化以下代码:
<bean id="" class="" init-method="" destroy-method="" scope="" autowire="">
<property></property>
<constructor-arg></constructor-arg>
</bean>
注解(很🐂B的)
1.注入类:
替换:<bean id = "" calss=""><bean>
位置:类
语法:@Component(value="注入容器中的id,如果省略id为类名且首字母小写,value属性名称可以省略")
eg:
<bean id="user" class="com.apesource.包.User"></bean>
||等价于||
@Component
Class User{}
注意:不能单独使用,必须配合扫描
<context:component-scan base-package=""></context:component-scan>
@Repository=====>注入数据访问层
@Service========>注入业务层
@Controller=====>注入控制层
以上三个注解与@Component功能语法一致
@Data
@ToString
@Component(value = "stu")//修饰类,将普通类注入到容器中;必须得到xml文件中做包扫描
public class Student {
private String sname;
private int sage;
public Student() {
System.out.println("===student的无参构造方法===");
}
}
扫包:
<context:component-scan base-package="com.li"></context:component-scan>
2.注入基本数据类型
@Value
含义:注入基本数据
替换:<property></property>
修饰:成员变量或对应的set方法
语法:@Value("数据内容")
@Value("${key}")
注意:如果需要动态获取则需要指定加载文件
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
@Autowired
语法:@Autowired(required = "true-默认、false、是否必须进行装配")
修饰:成员变量或对应的set方法
含义:按照通过set方法进行“类型装配”,set方法可以省略
注意:
1.默认是按照类型装配且同set方法
2.若容器中有一个类型可以与之匹配则装配成功,若没有一个类型可以匹配则报错
NoSuchBeanDefinitionException
3.若容器中有多个类型可以与之匹配,则自动切换为按照名称装配,若名称没有对应,则报错
NoUniqueBeanDefinitionException
@Data
@ToString
@Component(value = "stu")//修饰类,将普通类注入到容器中;必须得到xml文件中做包扫描
public class Student {
// @Value("haha")//注入基本数据前,先得将类注入到容器中
@Value("${msg1}")//配置文件见下msg.properties
private String sname;
// @Value("24")
@Value("${msg2}")
private int sage;
public Student() {
System.out.println("===student的无参构造方法===");
}
}
msg.properties
msg1=123
msg2=456
加载配置文件:
<context:property-placeholder location="classpath:msg.properties"></context:property-placeholder>
在service层装配dao层
@Service
public class UserServiceImp implements IUserService {
@Autowired//自动装配
IUserDao dao;
@Override
public void save() {
System.out.println("===serivce的新增===");
dao.save();
}
}
3.其他注解
@Primary
含义:首选项,当类型冲突的情况下,此注解修饰的类被列为首选(备胎扶正)
修饰:类
注意:不能单独使用,必须与@Component....联合使用
@Qualifier(value="名称")
含义:按照名称装配
修饰:成员变量
注意:不能单独使用,必须与@Autowired联合使用
@Resource(name="名称")
含义:按照名称装配
修饰:成员变量
注意:单独使用
@Scope
含义:配置类的作用域
修饰:类
注意:不能单独使用,必须与@Component....联合使用
@Scope("prototype")
@Scope("singleton")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
@PostConstruct:初始化,修饰方法 替换init-method
@PreDestroy:销毁,修饰方法 替换destory-method
IUserDao下面的两个实现类;当同一个接口下有多个实现类时,@Autowired会根据首字母小写进行寻找,若没找到则会报错,当实现方法上使用@Primary注解时,在多个实现类为找到匹配的实现类时就会默认使用被修饰的类。
//UserDaoImp
@Repository
public class UserDaoImp implements com.li.dao.IUserDao {
@Override
public void save() {
System.out.println("===dao的新增===");
}
}
//UserDaoImp2
@Repository
@Primary //同一个接口下面如果有多个实现类,并且实现类的名字没有匹配的,就会默认执行此类
public class UserDaoImp2 implements IUserDao {
@Override
public void save() {
System.out.println("===dao2的新增===");
}
}
SpringConfig
当使用类来充当配置类,来代替applicationConfig.xml文件
spring中的新注解
@Configuration
作用:指定当前类是一个配置类
细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
@ComponentScan
作用:用于通过注解指定spring在创建容器时要扫描的包
属性:
value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
我们使用此注解就等同于在xml中配置了:
<context:component-scan base-package="com.apesource"></context:component-scan>
@Bean
作用:用于把当前方法的返回值作为bean对象存入spring的容器中
属性:
name:用于指定bean的id。当不写时,默认值是当前方法的名称
@Import
作用:用于导入其他的配置类
属性:
value:用于指定其他配置类的字节码。
例子:@Import(SystemSpringConfig.class)
@PropertySource
作用:用于指定properties文件的位置
属性:
value:指定文件的名称和路径。
关键字:classpath,表示类路径下
配合@Value使用
例子:@PropertySource("classpath:SystemSpringConfig.properties")
dbutil_Spring_annotation
pom文件
<dependencies>
<!--spring-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.29</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
<!--dbutil-->
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.4</version>
</dependency>
<!--数据源-->
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.mchange</groupId>-->
<!-- <artifactId>c3p0</artifactId>-->
<!-- <version>0.9.5.2</version>-->
<!-- </dependency>-->
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.3.29</version>
</dependency>
</dependencies>
实体类pojo:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
private int aid;
private String aname;
private int amoney;
public Account(String aname, int amoney) {
this.aname = aname;
this.amoney = amoney;
}
}
dao层:
//接口
public interface IAccountMapper {
public void save(Account account);
public void update(Account account);
public Account findByName(String name);
public List<Account> findAll();
}
//实现类
@Repository
public class AccountMapperImp implements IAccountMapper{
/**
* DBUtil====>QueryRunner
* .query();====>执行所有查询
* .update();===>执行所有增删改
*
* */
@Autowired
QueryRunner queryRunner;
@Override
public void save(Account account) {
try {
queryRunner.update("insert into account(aname,amoney) values(?,?)",account.getAname(),account.getAmoney());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Override
public void update(Account account) {
try {
queryRunner.update("update account set aname=?,amoney=? where aid=?",account.getAname(),account.getAmoney());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Override
public Account findByName(String name) {
try {
Account query = queryRunner.query("select * from account where aname = ?", new BeanHandler<Account>(Account.class), name);
return query;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
@Override
public List<Account> findAll() {
try {
List<Account> query = queryRunner.query("select * from account", new BeanListHandler<Account>(Account.class));
return query;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
}
service层:
//接口方法同dao层接口
//实现类
@Service
public class AccountServiceImp implements IAccountService{
@Autowired
IAccountMapper mapper;
@Override
public void save(Account account) {
mapper.save(account);
}
@Override
public void update(Account account) {
mapper.update(account);
}
@Override
public Account findByName(String name) {
return mapper.findByName(name);
}
@Override
public List<Account> findAll() {
return mapper.findAll();
}
}
controller层:
//接口同dao层
//实现类:
@Controller
public class AccountControllerImp implements IAccountController{
@Autowired
IAccountService service;
@Override
public void save(Account account) {
service.save(account);
}
@Override
public void update(Account account) {
service.update(account);
}
@Override
public Account findByName(String name) {
return service.findByName(name);
}
@Override
public List<Account> findAll() {
return service.findAll();
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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 https://www.springframework.org/schema/context/spring-context.xsd">
<!--注入数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql//localhost:3306/2307db?serverTimezone=GMT"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!--注入queryRunner-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!--扫描包-->
<context:component-scan base-package="com.li"></context:component-scan>
</beans>
dbutil_Spring_config:
取消了annotation中的applicationConfig.xml取而代之的是配置类,其余不变。
resources中的jdbc.properties
msg1=com.mysql.cj.jdbc.Driver
msg2=jdbc:mysql://localhost:3306/2307db?serverTimezone=GMT
msg3=root
msg4=123456
config包下的ApplicationConfig:
//ApplicationConfig
@Configuration
@Import(DataSourceConfig.class)
@ComponentScan(basePackages = "com.apesource")
public class ApplicationConfig {
}
//DataSourcesConfig
@Configuration
@PropertySource(value = "classpath:jdbc.properties")
public class DataSourceConfig {
@Value("${msg1}")
private String msg1;
@Value("${msg2}")
private String msg2;
@Value("${msg3}")
private String msg3;
@Value("${msg4}")
private String msg4;
// <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
// <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
// <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/2307db?serverTimezone=GMT"></property>
// <property name="user" value="root"></property>
// <property name="password" value="123456"></property>
// </bean>
@Bean
public DataSource dataSource(){
try {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setDriverClass(msg1);
comboPooledDataSource.setJdbcUrl(msg2);
comboPooledDataSource.setUser(msg3);
comboPooledDataSource.setPassword(msg4);
return comboPooledDataSource;
} catch (PropertyVetoException e) {
e.printStackTrace();
}
return null;
}
// <bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
// <constructor-arg name="ds" ref="dataSource"></constructor-arg>
// </bean>
@Bean
public QueryRunner queryRunner(){
return new QueryRunner(dataSource());
}
}
dbutil_Spring_xml:
applicationContext.xml:
<!--注入数据源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/2307db?serverTimezone=GMT"></property>
<property name="user" value="root"></property>
<property name="password" value="123456"></property>
</bean>
<!--注入queryRunner-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<!--注入DAO-->
<bean id="mapperImp" class="com.apesource.mapper.AccountMapperImp">
<property name="queryRunner" ref="queryRunner"></property>
</bean>
<!--注入SERVICE-->
<bean id="serviceImp" class="com.apesource.service.AccountServiceImp">
<property name="mapper" ref="mapperImp"></property>
</bean>
<!--注入CONTROLLER-->
<bean id="controllerImp" class="com.apesource.controller.AccountControllerImp">
<property name="service" ref="serviceImp"></property>
</bean>
dao层:
//dao层接口:
public interface IAccountMapper {
public void save(Account account);
public void update(Account account);
public Account findByName(String name);
public List<Account> findAll();
}
//实现类
public class AccountMapperImp implements IAccountMapper{
/**
* DBUtil====>QueryRunner
* .query();====>执行所有查询
* .update();===>执行所有增删改
*
* */
QueryRunner queryRunner;
public void setQueryRunner(QueryRunner queryRunner) {
this.queryRunner = queryRunner;
}
@Override
public void save(Account account) {
try {
queryRunner.update("insert into account(aname,amoney) value(?,?)",account.getAname(),account.getAmoney());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Override
public void update(Account account) {
try {
queryRunner.update("update account set aname=?,amoney=? where aid=?",account.getAname(),account.getAmoney(),account.getAid());
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
@Override
public Account findByName(String name) {
try {
Account query = queryRunner.query("select * from account where aname = ?", new BeanHandler<Account>(Account.class), name);
return query;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
@Override
public List<Account> findAll() {
try {
List<Account> lists = queryRunner.query("select * from account", new BeanListHandler<Account>(Account.class));
return lists;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return null;
}
}
service层:
//接口同dao
//实现类
public class AccountServiceImp implements IAccountService {
IAccountMapper mapper;
public void setMapper(IAccountMapper mapper) {
this.mapper = mapper;
}
@Override
public void save(Account account) {
mapper.save(account);
}
@Override
public void update(Account account) {
mapper.update(account);
}
@Override
public Account findByName(String name) {
return mapper.findByName(name);
}
@Override
public List<Account> findAll() {
return mapper.findAll();
}
}
controller层:
//接口同dao
//controller层实现类
public class AccountServiceImp implements IAccountService {
IAccountMapper mapper;
public void setMapper(IAccountMapper mapper) {
this.mapper = mapper;
}
@Override
public void save(Account account) {
mapper.save(account);
}
@Override
public void update(Account account) {
mapper.update(account);
}
@Override
public Account findByName(String name) {
return mapper.findByName(name);
}
@Override
public List<Account> findAll() {
return mapper.findAll();
}
}
进阶版-dbutil-Spring-transaction
进阶目标:事务管理一定实在service业务层实现
实现步骤:
1.一个业务方法公共用一个连接对象
2.业务层公用的连接一起提交或回滚
包层级结构(模拟两个人转帐,正确的应该是转出人和转入人的金额一致,其余情况均不正常):
pojo实体类、mapper的实现类和接口、controller层的接口和实现类、service的接口和实现类同dbutil_Spring_xml
新增util:
ConnectionUtil:
public class ConnectionUtil {
//装配数据源
DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
Connection connection = null;
//获取连接
public Connection createCon(){
//判断
try {
connection = threadLocal.get();
if (connection==null){
connection = dataSource.getConnection();
threadLocal.set(connection);
}
return connection;
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
//关闭连接
public void closeCon(){
//解绑
threadLocal.remove();
}
}
TransactionUtil:
public class TransactionUtil {
//装配连接
ConnectionUtil connectionUtil;
public void setConnectionUtil(ConnectionUtil connectionUtil) {
this.connectionUtil = connectionUtil;
}
//开启事务
public void openTran(){
try {
connectionUtil.createCon().setAutoCommit(false);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//提交事务
public void commintTran(){
try {
connectionUtil.createCon().commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//回滚事务
public void rollbackTran(){
try {
connectionUtil.createCon().rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//关闭事务
public void closeTran(){
try {
connectionUtil.createCon().close();
connectionUtil.closeCon();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
测试类:
@RunWith(SpringJUnit4ClassRunner.class)//junit运行环境
@ContextConfiguration(locations = "classpath:applicationContext.xml")//加载spring主配置文件
public class Test01 {
@Autowired
private AccountControllerImp controllerImp;
@Test
public void show1(){
controllerImp.save(new Account("吉鑫",5000));
controllerImp.save(new Account("董建祥",5000));
}
@Test
public void show2(){
List<Account> all = controllerImp.findAll();
for (int i = 0; i < all.size(); i++) {
Account account = all.get(i);
System.out.println(account);
}
}
@Test
public void show3(){
controllerImp.transfer("吉鑫","董建祥",1000);
}
}