1. 什么是spring
Spring 被称为 J2EE 的春天,是一个开源的轻量级的 Java 开发框架, 具有控制反转(IoC)和面向切面(AOP)两大核心。Java Spring 框架通过声明式方式灵活地进行事务的管理,提高开发效率和质量
Spring框架是个轻量级的Java EE框架。所谓轻量级,是指不依赖于容器就能运行的。Struts、Hibernate也是轻量级的。Spring以IoC、AOP为主要思想,其中IoC,Inversion of Control 指控制反转或反向控制。在Spring框架中我们通过配置创建类对象,由Spring在运行阶段实例化、组装对象。AOP,Aspect Oriented Programming,面向切面编程,其思想是在执行某些代码前执行另外的代码,使程序更灵活、扩展性更好,可以随便地添加、删除某些功能。Servlet中的Filter便是一种AOP思想的实现。
Spring同时也是一个“一站式”框架,即Spring在JavaEE的三层架构[表现层(Web层)、业务逻辑层(Service层)、数据访问层(DAO层)]中,每一层均提供了不同的解决技术。如下:
表现层(Web层):Spring MVC
业务逻辑层(Service层):Spring的IoC
数据访问层(DAO层):Spring的jdbcTemplate
1.2 spring优势
(1)方便解耦,简化开发
(2)AOP编程支持
(3)声明式事务的支持
(4)方便集成各种优势框架
(5)降低JAVAEE API的使用难度
(6)JAVA源码是经典学习案例
spring项目实现步骤
1.创建maven项目
2.加入maven的依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<!--单元测试-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--spring依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
</dependencies>
<!-- 可加可不加-->
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.创建类(接口和他的实现类)、
package com.bjpowernode.service;
public interface SomeService {
void doSome();
}
package com.bjpowernode.service.impl;
import com.bjpowernode.service.SomeService;
public class SomeServiceImpl implements SomeService {
public SomeServiceImpl() {
System.out.println("SomeServiceImpl的无参构造方法");
}
@Override
public void doSome(){
System.out.println("doSome方法执行啦");
}
}
4.创建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-4.0.xsd">
<!--
告诉spring创建对象,
声明bean,就是告诉spring要创建某个类的对象
id:对象的自定义名称,唯一值。spring通过这个名称找到对象
class:类的全限定名称(不能是接口,因为spring是反射机制创建对象,必须使用类)
spring就完成SomeService someService=new SomeServiceImpl();
spring是把创建好的对象放入到map中,spring框架有一个map存放对象的
springMap.put(id的值,对象)
例如springMap.put("SomeService","new SomeService")
一个beans值
-->
<bean id="SomeService" class="com.bjpowernode.service.impl.SomeServiceImpl"/>
<bean id="SomeService1" class="com.bjpowernode.service.impl.SomeServiceImpl" scope="prototype"/>
<!--
spring能创建一个非自定义类的对象,创建一个存在的某个类的对象
-->
<bean id="mydate" class="java.util.Date"/>
</beans>
5.测试spring创建的类
每一个@Test能够单独运行
package com.bjpowernode;
import com.bjpowernode.service.SomeService;
import com.bjpowernode.service.impl.SomeServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Date;
public class Test1 {
@Test
public void test01(){
SomeService service=new SomeServiceImpl();
service.doSome();
}
/*
spring会默认创建对象的时间:在创建spring的容器时,会创建配置文件中所有的对象
//当创建两个bean标签时,SomeServiceImpl的无参构造方法执行了两次
spring创建对象:默认调用的是无参构造方法
*/
@Test
public void test02(){
//使用spring容器创建对象
//1.指定spring配置文件名称
String config="beans.xml";
//2.创建表示spring容器对象,ApplicationContext
//ApplicationContext就是表示spring容器,通过容器获取对象
//ClassPathXmlApplicationContex:表示从类路径中加载spring的配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
//3.从容器中获取某个对象,你要调用对象的方法
//getBean("配置文件中的bean的id值")
//(SomeService)将getBean("SomeService")内容强转成SomeServic类型
SomeService service=(SomeService) ac.getBean("SomeService");
//4.使用spring创建好的对象
service.doSome();//当创建两个bean标签时,SomeServiceImpl的无参构造方法执行了两次
}
//获取spring容器中java对象的信息
@Test
public void test03(){
String config="beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
//使用spring提供的方法,获取容器中定义的对象数量
int nums=ac.getBeanDefinitionCount();
System.out.println("容器中定义的对象数量"+nums);
//容器中每个定义的对象的名称
String names[]=ac.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
//获取一个非自定义的类的对象
@Test
public void test04(){
String config="beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
//使用getBean();
//(Date):强制类型转换
Date my=(Date) ac.getBean("mydate");
System.out.println("Date:"+my);
}
}
di:依赖注入,表示创建对象,给属性赋值
di的实现语法有两种
1.在spring的配置文件中,使用标签和属性完成,叫做基于XML的di实现(使用较少)
2.使用spring中的注解,完成属性赋值,叫做基于注解的di实现
di语法分类:
1.set注入(设置注入):spring调用类的set方法,在set方法可以实现属性的赋值
(使用set注入时,构造方法在set方法之前执行。set内部的方法可以自定义,构造后会显示出来)
80左右都是使用set注入
2.构造注入,spring调用类的有参构造方法,创建对象。在构造方法中完成赋值。
2.基于注解的di:通过注解完成java对象创建,属性赋值
使用注解步骤:
1.加入maven依赖spring-context,在加入spring-contextd的同时,间接加入spring-aop依赖使用注解必须使用spring-aop依赖
2.在类中加入spring的注解(多个不同功能的注解)
3.在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
需要学习的注解
@Component
@Respotory
@Service
@Controller
@Value
@Autowired
@Resource
1.@Component
2.@Respotory
3.@Service
4.@Controller
@Component:创建对象,等同于的功能
属性:value就是对象的名称,也就是bean的id值
value的值是唯一的。穿创建的对象在整个spring容器中就一个
位置:在类上面。
@Component(value="mystudent") 等同于
<bean id="myStudent" class="com.bjpowernode.ba01.Student">
和@Component功能一致的注解还有
1.@Repository(用在持久层类的上面):放在dao的实现类上面,
表示创建dao对象,dao对象是能访问数据库的。
2.@Service(用在业务层上面):放在service的实现类上面
创建service对象,service对象是做业务处理,可以有事务等功能。
3.@Controller(用在控制器上面):放在控制器(处理器)类的上面,创建控制器对象
控制器对象,能够接受用户提交的参数,显示请求的处理结果
以上三个注解的使用语法和@Component使用方法一样。但还有额外功能
当不知道具体使用的地方(持久层,业务层,控制器)使用@Component
*/
//使用value属性值,指定对象名称
//@Component(value="myStudent")
//省略value
//@Component("myStudent")
5.@Value
/*
@Value:简单类型属性赋值
属性:value是string类型的,表示简单类型的属性值
位置:1.在属性定义的上面,无需set方法,推荐使用
2.在set方法上面
@Value("张飞")
private String name;
@Value( "29")
private int age;
*/
5.@Autowired
/*
引用类型
@Autowired:spring框架提供的注解,实现引用类型的赋值
spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName,byType
@Autowired:默认使用的是byType自动注入
位置:
1.在属性定义的上面,无需set方法,推荐使用
2.在set方法上面,需要做的是:
1.属性上面加入@Autowired
2.在属性上面加入@Qualifier(value=“bean的id”):表示使用指定名称bean完成赋值。
如果要使用byName方式
*/
//声明一个引用类型
@Autowired
private School school;
@Value("nana")
private String name;
@Value("35")
private int age;
@Resource
/*
引用类型
@Resource 来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值
使用的也是自动注入原理,支持byName,byType,默认是byName
位置:1.在属性定义的上面,无需set方法,推荐使用
2,在set方法上面
*/
//默认是byName,byName不可使用,会使用byType
@Resource
private School school;
private String name;
private int age;
配置文件和注解方式使用选择:
需要经常改动就使用配置文件形式
不需要经常改动就使用注解方式
(通过分析可以发现,配置文件形式把复制和主类完全分开,分离特别彻底,需要改动时,把配置文件中的属性改变一下就完成了)但是注解方式,开发简单,易于维护,同时在查看相关信息时,方便查看。
现在开发一般注解为主(方便),配置文件为辅
aop
1.动态代理
实现方式:jdk动态代理,使用Jdk中proxy,Method,InvocationHandle创建代理对象,jdk动态代理要求目标类必须实现接口。
cglib动态代理:第三方的工具库,创建代理对象,原理是继承。通过继承目标类,创建子类。子类对象就是代理对象。要求目标类不能是final的,方法也不能是final的
2.动态代理作用:
(1)在目标类源码不改变的情况下,增加功能
(2)减少代码的重复
(3)专注业务逻辑代码
(4)解耦合,让你的业务功能和日志,事务非业务功能分离
3.aop:面向切面编程,基于动态代理,可以使用jdk,cglib两种代理方式
AOP就是动态代理规范化,把动态代理的实现步骤,方式都定义好了,让开发人员用一种统一的方式,就是动态代理。
4.AOP(Aspect Orient Programing)面向切面编程
Aspect:切面;给你的目标类增加的功能,就是切面。像日志,事务等
切面的特点:一般都是非业务的方法,独立使用的
Orient:面向,对着。
Programing:编程
OOP:面向对象编程
怎么理解面向切面编程。
(1)需要在分析项目功能时,找出切面
(2)合理安排切面的执行时间(在目标方法前,还是目标方法后)
(3)合理的安全切面执行的位置,在哪个类,哪个方法增加增强功能。
术语:
(1)Aspect:切面,表示增强的功能,就是一堆代码。完成某一个功能。非业务功能,常见的切面功能有日志,事务,统计信息,参数检查,权限验证
(2)JoinPoint:连接点,连接业务方法和切面的位置,就某类中的业务方法(一个)
(3)PointCut:切入点,指多个连接点方法的集合。多个方法(多个)
(4)目标对象:给哪个类的方法增加功能,这个类就是目标
(5)Advice:通知,通知表示切面功能执行的时间。
切面三要素:
(1)切面的功能代码,切面干什么。
(2)切面的执行位置,使用PointCut表示切面执行的位置
(3)切面的执行时间,使用Advice表示时间,在目标方法之前,还是之后
5.AOP的实现
aspectJ框架可以实现aop,并且集成在了spring框架中,实现方式
1.使用xml的配置文件:配置全局事务
2.使用注解,我们在项目中要做到aop功能,一般都需要注释,aspect有5个注释
6.Aspectj框架的使用
(1)切面的执行时间,这个执行时间在规范中叫做Advice(通知,增强)
在aspectj框架中使用注解表示,也可以使用xml配置。
@Before
@AfterReturning
@Around
@AfterThrowing
@After
AspectJ的切入点表达式(重点)
AspectJ表达式原型:
execution(modifiers-pattern? ret-type-pattern
declaring-type-pattern?name-pattern(param-pattern)
throws-pattern?)
解释:
modifiers-pattern:访问权限类型
ret-type-pattern:返回值类型
declaring-type-pattern:包名类名
name-pattern(param-pattern):方法名(参数类型和参数个数)
throws-pattern:抛出异常类型
?:表示可选部分
也就是:
execution(访问权限,方法返回值,方法声明(参数),异常类型)
切入点表达式要匹配的对象就是目标方法的方法名。所以,execution表达式中明显是方法的签名。注意:表达式中黑色文字表示可省略部分,各部分间用空格分开。在其中可以使用以下符号
- 0至多个任意字符
… 用在方法参数中,表示任意多个参数
用在包名后,表示当前包及其子包路径
- 用在类名后,表示当前类及其子类
用在接口后,表示当前接口及其实现类。
举例:
execution(public* *(..))
指定切入点为:任意公共方法,
execution(* set*(..))
指定切入点为:任何一个以“set”开始方法
execution(*com.xyz,service.*.*(..))
指定切入点为:定义在service包里任意类的任意方法
execution(*com.xyz,service.*.*(..))
指定切入点为:定义在service包或者子包里的任意列的任意方法。“...”出现在类名称中时,后面跟“*”,表示包,子包下的所有类。
execution(* *..service.*.*(..))
指定所有包干的service子包下所有类(接口)中所有方法为切入点
execution(* *..service.*.*(..))
指定只有一级包下的service子包下所有类(接口)中所有方法为切入点
快速实现接口的实现类:alt+enter
aspectj实现aop基本步骤
1.新建maven项目
2.加入依赖
(1)spring依赖
(2)aspectj依赖
(3)junit单元测试
3.创建目标类:接口和他的实现类。要做的是给类种的方法增加功能
4.创建切面类:普通类
(1):在类上面加入@Aspect
(2)在类中定义方法,方法就是切面要执行的功能代码
在方法的上面加入aspectj中的通知注解,例如@Before
有需要指定切入点表达式execution()
5.创建spring的配置文件:声明对象,把对象交给容器统一管理
声明对象你可以使用注解或者xml配置文件
1)声明目标对象
2)声明切面对象
3)声明aspectj框架中自动代理生成器标签。
自动代理生成器:用来完成代理对象的自动创建功能。
6.创建测试类,从spring容器汇中获取对象(实际就是代理对象)
通过代理执行方法,实现aop的功能增强。
spring整合mybatis步骤:
mybatis使用步骤:
1.定义dao接口,studentDao
2.定义mapper文件,studentDao.xml
3.定义mybatis的主配置文件mybatis.xml
4.创建到代理对象,
studentDao dao=SqlSession.getMapper(studentDao.class);
List<student> students=dao.selectStudent();
要使用dao对象,需要使用getMapper()方法,
怎么能使用getMapper()方法,需要哪些条件
1.获取SqlSession对象,需要使用SqlSessionFactory的openSession()方法
2.创建SqlSessionFactory对象。通过读取mybatis的主配置文件,能够创建SqlSessionFactory对象
需要SqlSessionFactory对象,使用Factory能获取SqlSession,有了SqlSession就能有dao,目的就是获取dao对象Factory创建需要读取主配置文件
主配置文件
<!-- mybatis的主配置文件 -->
<configuration>
<typeAliases>
<package name="com.southwind.entity"/>
</typeAliases>
<!-- 配置mybatis运行环境 -->
<environments default="development">
<!-- 配置mysql环境 -->
<environment id="development">
<!-- 配置事务类型 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置数据源(连接池) -->
<dataSource type="POOLED">
<!-- 配置连接数据库的4个基本信息 -->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
3.mapper映射配置文件
<!-- 注册AccountMapper.xml -->
<mappers>
<mapper resource="com/southwind/Mapper/AccountMapper.xml"></mapper>
<mapper resource="com/southwind/reposity/AccountReposity.xml"></mapper>
<mapper resource="com/southwind/reposity/StudentReposity.xml"></mapper>
<mapper resource="com/southwind/reposity/ClassesReposity.xml"></mapper>
</mappers>
spring需要创建以下对象
1.独立的连接池类对象,使用阿里的druid连接池
2.SqlSessionFactory对象
3.创建出dao对象
spring与mybatis整合步骤
1.新建maven项目
2.加入maven依赖
1)spring依赖
2)mybatis依赖
3)mysql驱动
4)spring的事务依赖
5)mybatis和spring集成的依赖
3.创建实体类
4.创建dao接口和mapper文件
5.创建mybatis主配置文件
6.创建Sdervice接口和实现类,属性是dao
7.创建spring的配置文件:什么mybatis的对象交给spring创建
1)数据源
2)SqlSessionFactory
3)dao对象
4)声明自定义的service
8.创建测试类,获取service对象,通过service调用dao完成数据库的访问。
====================================================
spring事务处理
1.什么是事务
事务是指一组aql语句,集合中有多条sql语句可能都是insert,update,deiete,我们希望这些语句都能执行成功或者失败。这写语句执行都是一致的,作为一个整体执行。
2.在什么时候想到使用事务
当我们的操作涉及到多个表,或者多个sql语句时。需要保证这些语句都是成功才能完成功能,或者都失败,如转账
事务放在service层上,因为会调用多个dao方法,执行sql语句
3.处理事务需要做什么
spring处理事务模型,使用的步骤都是固定的,把事务的使用信息提供给spring就可以了
(1)事务内部提交,回滚事务,使用的事务管理器对象,代替你完成commit,rollback,事务管理器是一个接口和他的众多实现类
接口:platformTransactionManager,定义了事务重要方法commit,rollback,
实现类:spring把每一种数据库访问技术对应的事务处理类都创建好了
mybatis访问数据库:spring创建好的是DataSourceTransactionManger
怎么使用:需要告诉spring你是用哪种数据库访问技术,
怎么告诉:声明数据库访问技术对于的事务管理器实现类,在speing的配置文件中使用声明
例如,使用mybatis数据库:
<bean id=”xxx” class=”...DataSourceTransactionManger”>
(2)说明方法需要的事务
1.事务的隔离级别:4个, mysql默认是repeatable_read
用于控制高并发情况下对事务安全性的控制
read_uncommitted:读未提交,未解决任何并发问题
read_committed:读已提交,解决脏读,存在不可重复读与幻读
repeatable_read:可重复读,解决脏读、不可重复读,存在幻读
serializable:串行化,不存在并发问题
2.事务超时时间:表示一个方法最长执行时间,如果方法执行时间超过了时间,事务就回滚
3.事务的传播行为:控制业务方法是不是业务的,是什么样的业务事务的
需要掌握以下三个
propagation_required
propagation_requires_new
propagation supports
(3)提交事务,回滚事务的时机
1.当你的业务方法,执行成功,没有异常抛出,当方法执行完毕,spring在方法执行后提交事务。事务管理器commit
2.当你的业务方法抛出运行是异常,spring执行回滚,调用事务管理器的rollback
运行时异常的定义:RunTimeException 和他的子类都是运行时异常,;如NullPointException , NumberFormatException
3.当你的业务方法抛出运行时异常,主要是受查异常时,提交事务
受查异常:在你写代码时,必须处理的异常。例如IoException,SQLException
总结spring事务:
1.管理事务的是事务管理和他的实现类
2.spring的事务是一个统一模型
(1)指定要使用的事务管理器实现类,使用
(2)指定哪些类,哪些方法需要加入事务的功能
(3)指定方法需要的隔离级别,传播行为,超时。
你需要告诉spring,你项目中的信息,方法的名称,方法的事务传播行为。
spring事务注解
@Transactional注解:将事务组织到响应public方法中,实现事务管理
@Transactiona可选属性
propagation:用于设置事务传播属性。该属性类型为propagation枚举,默认值为
propagation.REQUIRED
isolation:用于设置事务的隔离级别。属性类型为isolation枚举,默认为isolation.REQUIRED
readOnly:用于设置该方法对数据库的操作是否是只读的。该属性为boolean,默认为false
timeout:用于设置本操作与数据库连接的超时时限。单位为秒,类型为int,默认为-1,及没有时限
rollback:指定事务回滚的异常类。类型为Class[],默认值为空数组。当然,若只有一盒异常类时,可以不使用数组
rollbackForClassName:指定需要回滚的异常类类名。类型为class[],默认为空数组。当然,若只有一个异常类时,可以不使用数组
noRollbackFor:指定不需要回滚的异常类。类型为class[],默认为空数组。当然,若只有一个异常类时,可以不使用数组
noRollbackForClassName:指定不需要回滚的异常类类名,类型为class[],默认为空数组。当然,若只有一个异常类时,可以不使用数组
使用@Transactional步骤:
1.需要声明事务管理器对象
<bean id=”xxx” class=”DataSourceTransactionManger”>
2.开启事务注解驱动,告诉spring框架,我需要使用注解方式管理事务
spring使用aop机制,创建@Transactional所在的类代理对象,给方法加入事务的功能。
类上加@Transactional,则类中所有方法都会加入事务处理
方法上加@Transactional,只有该方法会进行事务处理
spring给业务方法加入事务
在你的业务方法执行之前,先开启事务,在业务方法之后提交或会晕事务,使用aop的环绕通知(环绕通知不需要写,加上@Transactional注解后,spring就给你自动实现了)
@Around(“你要参加的事务功能的业务方法名称”)
object myAround(){
开启事务,spring给你开启
try{
buy(1001,10);
spring事务管理.commit();
}catch(Exception e){
spring的事务管理.rollback()
}
}
3在你的方法上面加@Transactional
2.适合大型项目使用aspectj框架功能
实现步骤:都是在xml配置文件中实现
(1)要使用的是aspectj框架,需要计入依赖
<!-- aspectj依赖 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
(2)声明事务管理器对象
<bean id=”xx” class=”DataSourceTransactionManager”>
(3)声明方法需要的事务类型(配置方法的事务属性【隔离级别,传播行为,超时】)
(4)配置aop:指定哪些要创建的代理