1.spring的特点
非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API。
控制反转:IOC——Inversion of Control,指的是将对象的创建权交给Spring去创建。使用Spring之前,对象的创建都是由我们自己在代码中new创建。而使用Spring之后。对象的创建都是由给了Spring框架.
依赖注入:DI——Dependency Injection,是指依赖的对象不需要手动调用setXXX方法去设置,而是通过配置赋值。
面向切面编程:AOP——Aspect Oriented Programming,在不修改源代码的基础上进行功能扩展。
容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期。
组件化:Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的JDBCTemplate)。
2.spring的下载位置
最新正式发布版下载地址:JFrog
3.ioc在spring容器中的实现
beanfactory
applicationcontext
4.属性注入
setter注入在对应的xml文件进行对应的数据传递
构造器注入
特殊值的处理 若字面值中包含特殊字符,可以使用把字面值包裹起来
p名称空间,c名称空间
5.外部bean的作用就是当bean的属性是一个其他类型的对象是,可以在property或
内部bean当bean实例仅仅给一个特定的属性使用时,可以将其声明为内部bean。内部bean声明直接包含在
级联属性当bean的属性是一个对象,我们可以通过配置当前bean的方式给属性中对象的属性赋值,即给属性的属性赋值,这种方式我们称为给级联属性赋值。
集合属性的赋值
6.自动装配
手动装配:以value或ref的方式明确指定属性值都是手动装配。
自动装配:根据bean标签的autowire属性指定的装配规则,不需要明确指定,Spring自动将匹配的属性值注入bean中。
自动装配的规则,即autowire的属性值有:
no或default:不自动装配
byName:根据bean的属性名称自动装配,以当前bean的属性名作为id从IOC容器中寻找以实现装配。找到则装配,找不到则不装配。
byType:根据bean的属性类型自动装配。找到一个则装配,找到多个则报错,找不到则不装配。
constructor:根据bean的属性的构造器自动装配,不推荐使用。
7.工厂bean
Spring中有两种类型的bean,一种是普通bean,另一种是工厂bean,即FactoryBean。普通bean设置的类型就是返回的类型;工厂bean设置的类型可以和返回的类型不一样,其返回的类型通过该工厂bean的getObject方法指定。
创建工厂bean必须实现org.springframework.beans.factory.FactoryBean接口。
8.bean的作用域
| 类别 | 说明 |
|---|---|
| singleton | 在Spring的IOC容器中仅存在一个Bean实例 |
| prototype | 每次调用getBean方法都返回一个新的Bean实例 |
| request | 每次HTTP请求都会创建一个新的Bean实例,该作用域仅适用于WebApplicationContext环境 |
| session | 同一个Session会话共享一个Bean实例,该作用域仅适用于WebApplicationContext环境 |
9.bean的生命周期
通过构造器或工厂方法创建bean实例
为bean的属性设置值和对其他bean的引用
将bean实例传递给bean后置处理器的postProcessBeforeInitialization()方法
调用bean的初始化方法
将bean实例传递给bean后置处理器的postProcessAfterInitialization()方法
bean可以使用了
当容器关闭时调用bean的销毁方法
10.bean的开发方式
基于xml的方式开发
基于注解的方式进行开发
完全注解的开发创建配置类
@Configuration // 配置类标志注解
@ComponentScan(basePackages = "com.atguigu") // spring包扫描
@PropertySource("classpath:jdbc.properties") // 读取属性配置文件
@EnableTransactionManagement // 开启事务注解
11.spring的aop
代理模式分为动态代理,静态代理
动态代理的作用就是创建一个类在使用另一个类将这个类进行实现,将里面的方法重写进行增强的处理
动态代理proxy,cglib,jdk的动态代理
cglib动态代理是第三方动态代理,不是JDK内置的动态代理.JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLib了。CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。JDK动态代理与CGLib动态代理均是实现Spring AOP的基础。
Cglib和jdk动态代理的区别?
1、Jdk动态代理:利用拦截器(必须实现InvocationHandler)加上反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理
2、 Cglib动态代理:利用ASM框架,对代理对象类生成的class文件加载进来,通过修改其字节码生成子类来处理
什么时候用cglib什么时候用jdk动态代理?
1、目标对象生成了接口 默认用JDK动态代理
2、如果目标对象使用了接口,可以强制使用cglib
3、如果目标对象没有实现接口,必须采用cglib库,Spring会自动在JDK动态代理和cglib之间转换
动态代理的实现方式
基于接口实现动态代理: JDK动态代理
基于继承实现动态代理: Cglib、Javassist动态代理
12.spring的aop
通知类型就是在对应的方法上面添加通知类型的注解进行处理
使用就是先声明切入点表达式,在对方法进行通知类型的处理
springaop的实现方式
基于注解开发完成
基于xml文件的配置完成
13.操作数据库的jdbctemplate
- public class JdbcTemplateTest {
-
- ApplicationContext ioc = new ClassPathXmlApplicationContext("beans-jdbc.xml");
- JdbcTemplate jdbcTemplate = (JdbcTemplate) ioc.getBean("jdbcTemplate");
-
- /*
- 测试增删改
- */
- @Test
- public void testUpdate(){
- //写sql语句
- String sql = "insert into employee(last_name,email,salary) values(?,?,?)";
- //调用JdbcTemplate中的update方法
- jdbcTemplate.update(sql,"雷军","leijun@xiaomi.xom",9999.00);
- }
- }
批量处理增删改
JdbcTemplate.batchUpdate(String, List
Object[]封装了SQL语句每一次执行时所需要的参数
List集合封装了SQL语句多次执行时的所有参数
- /*
- 测试批量增删改
- */
- @Test
- public void testBatchUpdate(){
- //写sql语句
- String sql = "insert into employee(last_name,email,salary) values(?,?,?)";
- //创建一个List
- List
- Object[] arg1 = new Object[]{"李某宏","liyanhong@baidu.com",8888.00};
- Object[] arg2 = new Object[]{"刘某东","liuqiangdong@jd.com",7777.00};
- Object[] arg3 = new Object[]{"张某鸣","zhangyiming@douyin.com",6666.00};
- batchArgs.add(arg1);
- batchArgs.add(arg2);
- batchArgs.add(arg3);
- //调用JdbcTemplate中的批处理方法
- jdbcTemplate.batchUpdate(sql,batchArgs);
- }
查询数据
查询单行
- /*
- 测试获取一行数据
- */
- @Test
- public void testGetOne(){
- //写sql语句
- String sql = "select id,last_name lastName,email,salary from employee where id = ?";
- //创建RowMapper对象
- RowMapper
rowMapper = new BeanPropertyRowMapper<>(Employee.class); - //调用JdbcTemplate中的queryForObject方法
- Employee employee = jdbcTemplate.queryForObject(sql, rowMapper, 1);
- System.out.println(employee);
- }
查询多行
- /*
- 测试获取多行数据
- */
- @Test
- public void testGetAll(){
- //写sql语句
- String sql = "select id,last_name lastName,email,salary from employee";
- //创建RowMapper对象
- RowMapper
rowMapper = new BeanPropertyRowMapper<>(Employee.class); - //调用JdbcTemplate中的query方法
- List
employees = jdbcTemplate.query(sql, rowMapper); - //遍历
- for (Employee employee : employees) {
- System.out.println(employee);
- }
- }
14.spring的事务
基于注解开发的事务
在需要添加事务的方法上添加@Transactional注解
事务的传播行为就是在对应的transaction注解后面传播行为属性
事务的传播行为
| 传播属性 | 描述 |
|---|---|
REQUIRED | 如果有事务在运行,当前的方法就在这个事务内运行;否则就启动一个新的事务,并在自己的事务内运行。 |
REQUIRES_NEW | 当前的方法必须启动新事务,并在自己的事务内运行;如果有事务正在运行,应该将它挂起。 |
| SUPPORTS | 如果有事务在运行,当前的方法就在这个事务内运行,否则可以不运行在事务中。 |
| NOT_SUPPORTED | 当前的方法不应该运行在事务中,如果有运行的事务将它挂起 |
| MANDATORY | 当前的方法必须运行在事务中,如果没有正在运行的事务就抛出异常。 |
| NEVER | 当前的方法不应该运行在事务中,如果有正在运行的事务就抛出异常。 |
| NESTED | 如果有事务正在运行,当前的方法就应该在这个事务的嵌套事务内运行,否则就启动一个新的事务,并在它自己的事务内运行。 |
基于xml开发
15.事务的并发问题
脏读在事务进行提交但是读取的数据是未提交之前的数据
幻读向表中插入数据但是查询时查询不到,在次插入发现已经插入了
不可重复读 前后读取一条数据发现数据是不可重复的
16.事务的隔离级别事务与事务之间是隔离的,互不相关
读未提交:READ UNCOMMITTED
允许Transaction01读取Transaction02未提交的修改。里面的事务并发问题有脏读,幻读,不可重复读
读已提交:READ COMMITTED
要求Transaction01只能读取Transaction02已提交的修改。事务并发问题有幻读,不可重复读
可重复读:REPEATABLE READ
确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其它事务对这个字段进行更新。事务并发问题有幻读。解决事务并发的问题使用mvcc方式与原子性
串行化:SERIALIZABLE
确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其它事务对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。
mysql默认的事务隔离级别可重复读,Oracle的默认事务隔离级别是读已提交
spring的事务隔离级别的设置使用在@Transactional的isolation属性中设置隔离级别
17.事务的异常回滚
@Transactional注解中设置回滚的属性
rollbackFor或rollbackForClassName属性:指定遇到时必须进行回滚的异常类型,可以为多个。
如果是运行时异常,默认都是回滚的,如果是检查型异常,不回滚
如果想在发生指定的运行时异常出现时回滚,则使用rollbackfor进行设置
如果想在发生任何的检查型异常都回滚 rollbackfor=java.lang.Exception.class
noRollbackFor或noRollbackForClassName属性:指定遇到时不回滚的异常类型,可以为多个。
事务的超时间timeout,只读readonly
18.spring5的新特性
框架自带log4j2
支持了jsr