第一章
1.1 spring是什么
spring是分层的javaEE/SE轻量级的开源框架,以IOC控制反转和AOP面向切面编程为核心,提供了展现层springmvc和持久层spring jdbc 以及业务层事务管理等众多企业级应用技术,还可整合众多开源框架,慢慢成为使用最多的Java EE企业应用开源框架
1.2 spring的优势
- 方便解耦,简化开发
- 支持AOP编程
- 支持声明式的事务
- 方便程序测试
- 方便集成各种优秀框架
第二章 IOC的概念和简单使用
2.1 什么是IOC
IOC 控制反转 传统Java开发中,当我们需要在一个类中引入其他类时我们一般是new一个对象,而在spring中 我们可以通过配置将类交给spring创建,管理,我们只需在使用时从spring容器中获取这个对象就好了。
2.2 IOC简单入门
-
导入spring的开发包或者maven依赖
-
-
创建业务层和持久层接口和实现类
public interface IAccountService {
void saveAccount();
}
public class AccountServiceImpl implements IAccountService {
@Override
public void saveAccount() {
accountDao.saveAccount();
}
}
- 创建配置文件,配置类
<?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">
<!-- 配置 service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
</bean>
<!-- 配置 dao -->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
</beans>`
- 加载配置文件
//1.使用 ApplicationContext 接口,就是在获取 spring 容器
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
- 在业务层使用持久层类
//2.根据 bean 的 id 获取对象
IAccountService aService = (IAccountService) ac.getBean("accountService");
System.out.println(aService);`
2.3spring基于XML的IOC细节
2.3.1 spring中的工厂类结构图
2.3.2 bean标签
作用:用来配置Java类 使其加入spring容器,默认情况下调用的是类中的无参构造方法,若没有创建失败。
属性:
id:给对象一个唯一标识,用于获取对象
class:指定类的全限定名,用于反射创建对象
scope:指定类的作用范围
- singleton :单例的
- prototype:多例的
- request:创建一个对象存入request域
- session:创建一个对象存入session域
- global session
init-method:指定初始化方法名
destroy-method:指定销毁方法名
2.3.3 实例化bean的三种方式
- 使用默认无惨构造
- 使用实例工厂的方法创建对象
/**
* 模拟一个静态工厂,创建业务层实现类
*/
public class StaticFactory {
public static IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此种方式是:
使用 StaticFactory 类中的静态方法 createAccountService 创建对象,并存入 spring 容器
id 属性:指定 bean 的 id,用于从容器中获取
class 属性:指定静态工厂的全限定类名
factory-method 属性:指定生产对象的静态方法
-->
<bean id="accountService"
class="com.itheima.factory.StaticFactory"
factory-method="createAccountService"></bean>
- 使用静态工厂的方法创建对象
/**
* 模拟一个实例工厂,创建业务层实现类
* 此工厂创建对象,必须现有工厂实例对象,再调用方法
*/
public class InstanceFactory {
public IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此种方式是:
先把工厂的创建交给 spring 来管理。
然后在使用工厂的 bean 来调用里面的方法
factory-bean 属性:用于指定实例工厂 bean 的 id。
factory-method 属性:用于指定实例工厂中创建对象的方法。
-->
<bean id="instancFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService"
factory-bean="instancFactory"
factory-method="createAccountService"></bean>
2.4 spring的依赖注入
依赖注入:Dependency Injection。它是 spring 框架核心 ioc 的具体实现。
我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。 ioc
解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。 那这种业务层和持久层的依赖关系,在使用 spring
之后,就让 spring 来维护了。 简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。
- 构造方法注入
要求:类中有对应参数列表的构造方法
涉及标签:
constructor-arg
属性:
index:指定参数在构造函数列表的索引位置
type:指定参数的类型
name:指定参数在构造函数中的名称
value:指定参数值
ref:赋值其他bean类型
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
- set方法注入
要求: 类中须有set方法
涉及的标签:
property
属性:
name:set方法的形参
value:给属性赋值是基本类型和string类型的
ref:给属性赋值是其他bean类型
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<property name="name" value="test"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>
- 静态工厂的方法注入
- 实例工厂的方法注入
使用p标签注入属性 本质仍是调用set方法
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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="accountService"
class="com.itheima.service.impl.AccountServiceImpl4"
p:name="test" p:age="21" p:birthday-ref="now"/>
</beans>
注入集合属性
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
<!-- 给数组注入数据 -->
<property name="myStrs">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!-- 注入 list 集合数据 -->
<property name="myList">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<!-- 注入 set 集合数据 -->
<property name="mySet">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<!-- 注入 Map 数据 -->
<property name="myMap">
<props>
<prop key="testA">aaa</prop>
<prop key="testB">bbb</prop>
</props>
</property>
<!-- 注入 properties 数据 -->
<property name="myProps">
<map>
<entry key="testA" value="aaa"></entry>
<entry key="testB">
<value>bbb</value>
</entry>
</map>
</property>
</bean>
第三章 基于注解的IOC配置
配置spring扫描
<!-- 告知 spring 创建容器时要扫描的包 -->
<context:component-scan base-package="com.itheima"></context:component-scan>
3.1 常用注解
- @Component
作用:把资源让spring管理 相当于配置一个bean
属性:value :指定bean的id 默认为类的类名 首字母小写
@Controller @Service @Repository
以上三个注解都是@Component的衍生注解,只不过为了更符合语境
2.@Autowired
作用:自动按照类型注入,当使用注解注入时 set方法可以省略,只能注入其他bean类型
3.@Qualifier
作用:在自动类型注入的基础上,再按照id注入 在给字段注入时不能独立使用
属性:value :指定bean的id
4.@Resource
作用:直接按照bean的id注入 只能注入其他bean类型
属性:name:指定bean的id
5.@Value
作用:只能注入基本类型和string类型
属性:value :指定值
6.@Scope
作用:用于指定bean的作用范围
属性:value :指定范围(singleton,request,session,prototype)
7.@PostConstruct
作用:用于指定初始化方法
8.@PreDeatroy
作用:用于指定销毁方法
3.2 spring 注解和xml的选择
3.3 纯注解模式
涉及注解:
- @Configuration
作用:用于指定当前类是一个 spring 配置类,当创建容器时会从该类上加载注解。获取容器时需要使用
AnnotationApplicationContext(有@Configuration 注解的类.class)。
属性:
value:用于指定配置类的字节码这里是引用
2.@ComponentScan
作用: 用于指定 spring 在初始化容器时要扫描的包。作用和在 spring 的 xml 配置文件中的:
<context:component-scan base-package=“com.itheima”/>是一样的。
属性:
basePackages:用于指定要扫描的包。和该注解中的 value 属性作用一样。
3.@Bean
作用: 该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。
属性: name:给当前@Bean注解方法创建的对象指定一个名称(即 bean 的 id)。
4.@PropertySource
作用:用于加载.properties 文件中的配置。
属性:
value[]:用于指定 properties 文件位置。如果是在类路径下,需要写上 classpath:
5.@Import
作用:用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration 注解。当然,写上也没问题。 属性:
value[]:用于指定其他配置类的字节码。
通过注解获取容器
ApplicationContext ac =
new AnnotationConfigApplicationContext(SpringConfiguration.class);
第四章 spring整合Junit
-
导入Junit的jar包
-
使用@RunWith注解替换原有的运行器
@RunWith(SpringJUnit4ClassRunner.class)
3.加载配置文件
```
@ContextConfiguration(locations= {"classpath:bean.xml"})
```
4.方法上加@Test注解
5. 注入变量
```
@Autowired
private IAccountService as ;
```
第五章 AOP面向切面编程
5.1 什么是aop
aop即面向切面编程,通过预编译和运行期动态代理的技术实现程序功能的一种技术。简单来说就是把我们程序中重复的代码提取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的情况下,对我们已有的方法进行增强。
5.2 aop的作用以及优势
- 作用:在程序运行期间,对已有方法进行增强
- 优势:减少代码重复,提高开发效率,维护方便
5.3 aop的应用
-
导入必备jar包或依赖
-
创建spring配置文件
-
配置spring的IOC
-
抽取公共代码制作成通知
-
配置aop
a.把通知类用bean标签配置起来<!-- 配置通知 --> <bean id="txManager" class="com.itheima.utils.TransactionManager"> <property name="dbAssit" ref="dbAssit"></property> </bean>
b.使用aop:config 声明aop配置
aop:config: 作用:用于声明开始 aop 的配置 <aop:config> <!-- 配置的代码都写在此处 --> </aop:config>
c.使用aop:aspect 配置切面
aop:aspect: 作用:用于配置切面,就是切入点和通知的结合 属性: id:给切面提供一个唯一标识。 ref:引用配置好的通知类 bean 的 id。 <aop:aspect id="txAdvice" ref="txManager"> <!--配置通知的类型要写在此处--> </aop:aspect>
d.使用aop:pointcut 配置切入点表达式
aop:pointcut: 作用:用于配置切入点表达式。就是指定对哪些类的哪些方法进行增强。 属性: expression:用于定义切入点表达式。 id:用于给切入点表达式提供一个唯一标识 <aop:pointcut expression="execution( public void com.itheima.service.impl.AccountServiceImpl.transfer( java.lang.String, java.lang.String, java.lang.Float) )" id="pt1"/>
e.使用aop:xxx配置对应的通知类型
aop:before 作用:用于配置前置通知。指定增强的方法在切入点方法之前执行 属性: method:用于指定通知类中的增强方法名称 ponitcut-ref:用于指定切入点的表达式的引用 poinitcut:用于指定切入点表达式 执行时间点:切入点方法执行之前执行 <aop:before method="beginTransaction" pointcut-ref="pt1"/> aop:after-returning 作用:用于配置后置通知 属性: method:指定通知中方法的名称。 pointct:定义切入点表达式 pointcut-ref:指定切入点表达式的引用 执行时间点:切入点方法正常执行之后。它和异常通知只能有一个执行 <aop:after-returning method="commit" pointcut-ref="pt1"/> aop:after-throwing 作用:用于配置异常通知 属性: method:指定通知中方法的名称。 pointct:定义切入点表达式 pointcut-ref:指定切入点表达式的引用 执行时间点:切入点方法执行产生异常后执行。它和后置通知只能执行一个 <aop:after-throwing method="rollback" pointcut-ref="pt1"/> aop:after 作用:用于配置最终通知 属性: method:指定通知中方法的名称。 pointct:定义切入点表达式 pointcut-ref:指定切入点表达式的引用 执行时间点:无论切入点方法执行时是否有异常,它都会在其后面执行。 <aop:after method="release" pointcut-ref="pt1"/>
实例
<aop:config>
<!--配置切面-->
<aop:aspect id="aspect1" ref="mtm">
<!--配置通知类型-->
<!-- <aop:before method="t1" pointcut-ref="pointcut"/>
<aop:after method="t4" pointcut-ref="pointcut"/>-->
<aop:after-returning method="t2" pointcut-ref="pointcut"/>
<aop:after-throwing method="t3" pointcut-ref="pointcut"/>
<!--配置切入点表达式-->
<aop:pointcut id="pointcut"
expression="execution(* com.muyi.service.UserService.*(..))"/>
</aop:aspect>
</aop:config>
使用注解
在切面类上增加@Aspact注解 声明这是一个切面类
@Aspect
public class MyTransactionManager {
}
在方法上加通知类型注解声明讲此方法切入到某个切点的某个阶段
@Before(value = "execution(* com.muyi.service.UserService.*(..))")
public void t1(){
System.out.println("this is 前置通知before-------------------");
}
在spring的配置文件中开启aop的注解扫描
<!--开启对aop的注解支持-->
<aop:aspectj-autoproxy/>
还可配置切入点表达式
@Pointcut(value = "execution(* com.muyi.service.UserService.*(..))")
private void pt1(){}
引入
@Before(value = "pt1()")
public void t1(){
System.out.println("this is 前置通知before-------------------");
}
第六章 spring中的事务控制
6.1 我们需要知道的
- javaEE体系进行分层开发,spring提供分层设计业务层的事务处理解决方案
- spring为我们提供了一系列的事务控制的接口
- spring的事务控制都是基于aop的,可以使用编程的方式实现 也可使用配置的方式实现
6.2 接口介绍
我们在开发中常用的是它的实现类
真正管理事务的对象
org.springframework.jdbc.datasource.DataSourceTransactionManager 使用 Spring
JDBC 或 iBatis 进行持久化数据时使用
org.springframework.orm.hibernate5.HibernateTransactionManager 使用
Hibernate 版本进行持久化数据时使用
6.3 事务的隔离级别
6.4 事务的传播行为
REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选
择(默认值)
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常
REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
NEVER:以非事务方式运行,如果当前存在事务,抛出异常
NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作。
6.5 实际应用中配置事务
- 配置事务管理器,注入数据源datasource
<!-- 配置一个事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入 DataSource -->
<property name="dataSource" ref="dataSource"></property>
</bean>
- 配置事务的通知引用事务管理器
<!-- 事务的配置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
</tx:advice>
- 配置事务的属性
<!--在 tx:advice 标签内部 配置事务的属性 -->
<tx:attributes>
<!-- 指定方法名称:是业务核心方法
read-only:是否是只读事务。默认 false,不只读。
isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。
propagation:指定事务的传播行为。
timeout:指定超时时间。默认值为:-1。永不超时。
rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。没有默认值,任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚。没有默认值,任何异常都回滚。
-->
<tx:method name="*" read-only="false" propagation="REQUIRED"/>
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
</tx:attributes>
- 配置aop的切入点表达式
<!-- 配置 aop -->
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut expression="execution(* com.itheima.service.impl.*.*(..))"
id="pt1"/>
</aop:config>
- 配置切入点表达式和事务通知的对应关系
<!-- 在 aop:config 标签内部:建立事务的通知和切入点表达式的关系 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
使用注解方式
- 配置事务管理器
- 在业务层使用@Transcational注解
@Service("accountService")
@Transactional(readOnly=true,propagation=Propagation.SUPPORTS)
public class AccountServiceImpl implements IAccountService {
@Transactional(readOnly=false,propagation=Propagation.REQUIRED)
public void transfer(String sourceName, String targeName, Float money) {}
}
该注解的属性和 xml 中的属性含义一致。该注解可以出现在接口上,类上和方法上。
出现接口上,表示该接口的所有实现类都有事务支持。
出现在类上,表示类中所有方法有事务支持
出现在方法上,表示方法有事务支持。
以上三个位置的优先级:方法>类>接口
- 在配置文件中开启spring对注解事务的支持
<!-- 开启 spring 对注解事务的支持 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
不使用xml的配置方式
@Configuration
@EnableTransactionManagement
public class SpringTxConfiguration {
//里面配置数据源,配置 JdbcTemplate,配置事务管理器。在之前的步骤已经写过了。
}