Spring
一、spring的概述
1. 概念:Spring是分层的Java SE/EE应用 full-stack轻量级开源框架,以IoC(Inverse Of Control:反转控制)和AOP(Aspect
Oriented Programming:面向切面编程)为内核
3. 优势:
1. 方便解耦,简化开发
2. AOP编程的支持
3. 声明式事务的支持
4. 方便程序的测试
5. 方便集成各种优秀框架
6. 降低JavaEE API的使用难道
7. Java源码是经典学习范例
二、IOC的概念及作用
1. 程序的耦合:耦合性也叫耦合度,是对模块间关联程度的度量。
1. 在软件工程中,耦合指的就是对象之间的依赖性。对象之间的耦合越高,维护成本越高。
2. 总结:耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采取以下原则:如果模块间必须存在耦合,就尽量使用
数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合
2. 工厂模式解耦
在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件
, 把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。
那么,这个读取配置文件,创建和获取三层对象的类就是工厂
3. 控制反转
1. 把创建对象的权利交给框架,是框架的重要特征,并非面向对象编程的专业术语,
2. 包括:1)依赖注入 2)依赖查询
4. ioc的作用:削弱计算机程序的耦合(解除我们代码中的依赖关系)
三、使用spring的IOC解决程序的耦合
1. spring的目录结构:
1. docs :API 和开发规范
2. libs :jar 包和源码.
3. schema :约束
4. 注意:spring5使用jdk8编写的,所以要求jdk版本是8及以上,同时tomcat的版本要求8.5以上
2. 基于XML的配置
1. 导入jar包
2. 创建一个任意名称的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" >
</ beans>
3. 让 spring 管理资源,在配置文件中配置 service 和 dao
bean 标签:用于配置让 spring 创建对象,并且存入 ioc 容器之中
id 属性:对象的唯一标识。
class 属性:指定要创建对象的全限定类名
< bean id = " service类名" class = " service的全限定类名" > </ bean>
< bean id = " dao类名" class = " dao的全限定类名" > </ bean>
4. 测试类配置
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
service接口 as =ac.getBean("service的类名",service接口.class)
3. ApplicationContext的子实现类
1. FileSystemXmlApplicationContext:读取系统任意一路径下的配置文件(不常用)
2. ClassPathXmlApplicationContext:读取路径下的配置文件(推荐)
3. AnnotationConfigApplicationContext:通常用来读取注解
4. BeanFactory和ApplicationContext的区别
BeanFactory 才是 Spring 容器中的顶层接口。
ApplicationContext 是它的子接口。
BeanFactory 和 ApplicationContext 的区别:
创建对象的时间点不一样。
ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
BeanFactory:什么使用什么时候创建对象
5. bean 标签
1. 属性:
1. id:给对象在容器中提供一个唯一标识。用于获取对象。
2. class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
3. scope:指定对象的作用范围
1. singleton :默认值,单例的.
2. prototype :多例的.
3. request :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中.
4. session :WEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中.
5. global session :WEB 项目中,应用在 Portlet 环境.如果没有 Portlet 环境那么globalSession 相当于 session.
4. init-method:指定类中的初始化方法名称。
5. destroy-method:指定类中销毁方法名称
2. 作用范围以及生命周期
1. 单例对象:scope="singleton"
1. 作用范围:一个应用只有一个对象的实例。它的作用范围就是整个引用。
2. 生命周期:
对象出生:当应用加载,创建容器时,对象就被创建了。
对象活着:只要容器在,对象一直活着。
对象死亡:当应用卸载,销毁容器时,对象就被销毁了。
2. 多例对象:scope="prototype"
1. 作用范围:每次访问对象时,都会重新创建对象实例。
2. 生命周期:
对象出生:当使用对象时,创建新的对象实例。
对象活着:只要对象在使用中,就一直活着。
对象死亡:当对象长时间不用时,被 java 的垃圾回收器回收了。
3. 实例化Bean的三种方式
1. 方式一:使用无参构造方法(我们创建dao对象或者service对象)
< bean id = " accountService" class = " 全限定类名" > </ bean>
2. 方式二:使用实例工厂
< bean id = " instanceFactory" class = " 全限定类名" > </ bean>
< bean id = " accountService" factory-bean = " instanceFactory" factory-method = " getAccountService(非静态方法)" > </ bean>
3. 方式三:使用静态工厂
< bean id = " accountService" class = " 全限定类名" factory-method = " getAccountService(静态方法)" > </ bean>
6. 依赖注入
1. 概念:Dependency Injection。它是 spring 框架核心 ioc 的具体实现。
2. 构造函数注入:
1. 使用构造函数的方式,给 service 中的属性传值
要求:
类中需要提供一个对应参数列表的构造函数。
涉及的标签:
constructor-arg
属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称 用这个找给谁赋值(常用)
===上面三个都是找给谁赋值,下面两个指的是赋什么值的=======
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
3. set注入
< bean id = " accountService2" class = " 全限定类名" >
< property name = " " value = " " > </ property>
...
</ bean>
属性:
name:指定参数在构造函数中的名称 用这个找给谁赋值
value:它能赋的值是基本数据类型和 String 类型
ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 bean
四、ioc部分注解
在头文件添加一下内容(可实现注解)
xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd"
1. 设置包扫描
< context: component-scan base-package = " com.corn" > </ context: component-scan>
2. 声明bean对象
1. @Component
属性:value--> 设置bean对象的id,此属性可选的,如果不写的话,默认是类名,单首字母小写
代替:bean标签<bean id="" class=""></bean>
2. @Controller --> 一般用于web层
3. @service --> 一般用于service层
4. @Repository --> 一般用于dao层
注意:上面三个注解的函数就是为了做到见名知意
3. 用于注入数据的注解
1. @Autowired:按照类型进行注入
2. @Qualifier:属性value --> 指定的是注入的bean的id
3. @Resource :按照类型注入的基础,按照id进行bean对象的注入,name的属性设置的是bean的id
4. 替代了上面两个注解
1. @Value:给基本数据类型和string类型的数据进行注入 spE1 spring中的e1表达式${表达式}
4. 改变作用范围
1. @Scope :指定bean的作用范围 属性:value -- > 范围的取值
5. 生命周期相关的:
1. @postConstruct :用于指定初始化方法
2. @PreDestroy :用于指定销毁方法
6. spring注解和XML的选择问题
1. 注解的优势:配置简单,维护方便
2. XML的优势:修改时,不用改源码。不涉及重新编译和部署
7. (总结)spring管理bean方式的比较:
基于XML配置 基于注解配置 Bean的定义 @Component @Controller @service @Repository Bean名称 通过id或者name指定 @Component("…") Bean注入 或者通过p命名空间 @Autowired:按照类型进行注入@Qualifier:按照名称注入 生命过程 init-method、destroy-method @postConstruct:初始化 @PreDestroy:销毁 Bean作用范围 范围scope属性 @Scope:设置作用范围 适合场景 Bean来自第三方 Bean的实现类由用户自己开发
五、ioc全注解
1. @Configuration
1. 作用:指定当前类是一个配置类
2. 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
2. @ComponentScan
1. 作用:用于通过注解指定spring在创建容器时要扫描的包
2. 属性:
value:它和basePackages的作用是一样的,都是用于指定创建容器时要扫描的包。
我们使用此注解就等同于在xml中配置了:
< context: component-scan base-package = " com.corn" > </ context: component-scan>
3. @Bean
1. 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中
2. 属性:
name:用于指定bean的id。当不写时,默认值是当前方法的名称
3. 细节:
当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有可用的bean对象。
查找的方式和Autowired注解的作用是一样的
4. AnnotationConfigApplicationContext实现类
1. 读取注解创建容器
ApplicationContext ac= new AnnotationConfigApplicationContext ( 注解配置类名. class )
5. @Import
1. 作用:用于导入其他的配置类
2. 属性:
value:用于指定其他配置类的字节码。
当我们使用Import的注解之后,有Import注解的类就父配置类,而导入的都是子配置类
6. @PropertySource
1. 作用:用于指定properties文件的位置
2. 属性:
value:指定文件的名称和路径。
关键字:classpath,表示类路径下
六、spring整合junit
1. 引入jar包的坐标
spring- test 5.0 .2
2. 设置运行器
@RunWith ( )
3. 指定配置文件所在的位置或者配置类的字节码对象
1. @ContextConfiguration ( classes = 配置类名. class ) -- > 配置类
2. @ContextConfiguration ( locations= "classpath:配置文件名.xml" ) -- > 配置文件
注意:当我们使用spring 5. x版本的时候,要求junit的jar必须是4.12 及以上
七、动态代理
1. 使用CGLIB
1. 由于CGLIB是第三方的代理技术,需要引入jar包cglib 2.1_3
2. 使用CGLIB
八、AOP
ThreadLocal类:
ThreadLocal< Connection> :将连接和线程绑定起来
void set ( T value) - > 将连接存储起来,并和线程绑定到一起
T get ( ) - > 在线程中获取连接,同一个线程获取到的是同一个连接
1. 作用:在程序运行期间,不修改源码对已有方法进行增强
2. 优势:
1. 减少重复代码
2. 提高开发效率
3. 维护方便
3. 实现方式:使用动态代理技术
4. 专业术语:
1. Joinpoint ( 连接点)
2. Pointcut ( 切入点)
3. target ( 目标对象)
4. proxy ( 代理)
5. Aspect ( 切面)
6. Advice ( 通知)
1. 类型:
1. 前置通知(aop: before)
2. 后置通知(aop: returning)
3. 异常通知 ( aop: after- throwing)
4. 最终通知 ( aop: after)
5. 环绕通知 ( aop: before)
5. 使用
1. 引入jar包的坐标
aspectjweaver 1.8 .7
2. 配置
< ! -- 配置AOP-- >
< aop: config>
< ! -- 配置切面-- >
< aop: aspect id= "id" ref= "配置事务管理器的id" >
< ! -- 配置通知的类型,并且建立通知的方法和切入点方法的关联-- >
< aop: before method= "增强的方法" pointcut= "execution(切入点表达式)" > < / aop: before>
< / aop: aspect>
< / aop: config>
3. 切入点表达式:
访问修饰符 返回值类型 包名. 类名. 方法名(参数类型的列表)
规则:
1. 修饰符可以省略
2. `* `:返回值类型,包名,一个`* `只能代替一级包,类名,方法名,参数
3. . . :当前包及其子包,参数类型列表
开发中一般的写法:
`* ` com. itcast. service. impl. *. *( . . )
6. 环绕通知:
1. 定义通知方法
public Object aroundAdvice ( ProceedingJoinPoint pop) {
try {
Object r= null;
Object[ ] args= pop. getArgs ( ) ;
this . beginTransaction ( ) ;
r= pop. proceed ( args) ;
this . commit ( ) ;
return r;
} catch ( Throwable t) {
this . rollback ( ) ;
throw new RuntimeException ( t) ;
} finally {
this . release ( ) ;
}
2. 在配置文件中配置
九、注解AOP
1. 在配制文件中开启注解AOP
< aop: aspectj- autoproxy> < / aop: aspectj- autoproxy>
2. 使用注解开发
1. @Aspect :代替< aop: aspect id= "id" ref= "配置事务管理器的id" >
2. @Bfore ("pt1()" )
3. @AfterReturning ("pt1()" )
4. @AfterThrowing ("pt1()" )
5. @after ("pt1()" )
6. @Before ("pt1()" )
7. @Pointcut
创建一个方法pt1使用在其上参数为:切入点表达式
十、声明式事务
1. PlatformTransactionManager(接口)
子类:
DataSourceTransactionManager(是子实现类)
此接口提供事务操作的方法,包含有3 个具体操作
1. 获取事务状态信息
TransactionStatus getTransaction(TransactionDefinition definition)
2. 提交事务
void commit(TransactionStatus status)
3. 回滚事务
void rollback(TransactionStatus status)
2. TransactionDefinition:事务定义的信息
1. int getPropagationBehavior(): 获取传播行为
REQUIRED -- > 肯定有事务的管理
SUPPORTS -- > 有事务。进行事务的管理,没有的话,不进行事务的管理
2. int getIsolationLevel():-- > 获取隔离的级别
ISOLATION_READ_UNCOMMITTED
ISOLATION_READ_COMMITTED
ISOLATION_REPEATABLE_READ
ISOLATION_SERIALIZABLE
3. int getTimeout ( ) : -- > 获取超时时间
4. boolean isReadOnly(): -- > 获取是否只读
查询操作可以设置为只读,增删改操作必须不能是只读
3. TransactionStatus 事务的状态
4. 事务的属性
1. isolation:用于指定事务的隔离级别,默认值是DEFAULT,表示使用默认隔离级别
2. peopagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择,查询方法可以选择SUPPORTS
3. read- only:用于指定事务是否只读。只要查询方法才能设置为true ,默认值为false ,表示读写
4. timeout:用于指定事务的超时时间,默认值为- 1 ,表示永不超时,如何指定了数值,以秒为单位
5. rollback- for :用于指定一个异常,当产生该异常时,事务回滚,产生其他异常,事务不回滚,没有默认值。表示任何异常都回滚
6. no- rollback- for :用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常,事务回滚,没有默认值表示任何异常都回滚
十一、声明式事务的xml使用
1. 在bean.xml中的配置
< bean id = " transactionManager" class = " org.springframework.jdbc.datasource.DataSourceTransactionManager" >
< property name = " dataSource" ref = " dataSource" />
</ bean>
< tx: advice id = " txadvice" transaction-manager = " transactionManager" >
< tx: attributes>
< tx: method name = " *" read-only = " false" propagation = " REQUIRED" />
< tx: method name = " find*" read-only = " true" propagation = " SUPPORTS" />
</ tx: attributes>
</ tx: advice>
< aop: config>
< aop: pointcut id = " pt1" expression = " execution(* com.corn.service.*.*(..))" />
< aop: advisor advice-ref = " txadvice" pointcut-ref = " pt1" />
</ aop: config>
十二、基于注解的声明式事务
1. @EnableTransactionManagement -- > 相当于< aop: aspectj- autoproxy> < / aop: aspectj- autoproxy>
2. 写一个TransactionConfig类,用于配置事务管理器,同时开通spring对注解事务的支持
public class TransactionConfig {
@Bean ( name = "transactionManager" )
public PlatformTransactionManager createTransactionConfig ( DataSource dataSource) {
return new DataSourceTransactionManager ( dataSource) ;
}
}
3. service实现类方法上的注解
@Transactional ( propagation = Propagation. REQUIRED, readOnly = false )