1.IOC(控制反转)
IOC容器的底层数据结构:ConCurrentHashMap(key,value都不为空)
IOC采用依赖倒置设计原则,一种主从换位的设计思想
IOC和DI的区别:描述的是同一件事情,从不同的角度出发。从对象的角度,实现了控制反转,将控制权转到IOC容器中;DI是从容器的角度出发,将依赖的其他对象注入进去。
注入方式:构造器注入(默认)、setter方式注入(推荐)、接口方式注入(带侵入性,不推荐)
类结构:BeanFactory(顶层接口)——ApplicationContext(常用)——ClassPathXmlApplicationContext(类的根路径)——FileSystemXmlApplicationContext(磁盘路径)——AnnotationConfigApplicationContext(注解配置)
BeanFactory和ApplicationContext区别:ApplicationContext为子接口,只要一读取配置文件,默认情况下创建对象;BeanFactory什么时候使用什么时候创建对象
Bean 的作用域:
- singleton:仅存在一个,单例存在
(默认使用,单例导致线程不安全,可用ThreadLocal解决线程安全) - prototype:调用Bean时,都返回一个新的实例(线程安全)
- request:HTTP请求都会创建一个新的Bean
- session:同一个HTTP Session共享一个Bean,不同Session使用不同的
- global-session:全局session
(后三个仅适用于WebApplicationContext环境)
单例模式下的线程并发:
- ThreadLocal:利用”空间换时间“,为每一个线程产生一个变量副本,隔离多个线程对数据的访问冲突;因为每个线程都有了自己的变量副本,就没必要对变量进行同步了
- 线程同步加锁:利用”时间换空间“,还是同一个变量,不同的线程在访问前都需要获取锁,没获得锁的线程需要排队
2.AOP(面向切面编程)
实现方式:基于动态代理技术
静态代理:在运行前手动创建的代理类,代码中显示指定的代理
动态代理:在程序运行时自动创建的代理类,生成class文件;方便对代理类进行统一处理,不需要修改代理类的方法
动态代理实现方式:
- 基于接口:实现类所实现的接口作为参数,InvocationHandler接口(要求被代理类至少实现一个接口)
- 基于子类:对代理类的目标类生成一个子类,Cglib
通知类型:
- 前置通知(Before advice):在某个连接点(Join point)之前执行的通知,但这个通知不能阻止连接点的执行(除非它抛出一个异常)。
- 返回后通知(After returning advice):在某个连接点(Join point)正常完成后执行的通知。例如,一个方法没有抛出任何异常正常返回。
- 抛出异常后通知(After throwing advice):在方法抛出异常后执行的通知。
- 后置通知(After advice):当某个连接点(Join point)退出的时候执行的通知(不论是正常返回还是发生异常退出)。
- 环绕通知(Around advice):默认使用,这是最强大的一种通知类型。包围一个连接点(Join point)的通知,如方法调用。环绕通知可以在方法前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
3.注解
自动装配:
- @Required 注解应用于 bean 属性的 setter 方法
- @Autowired 注解可以除去 setter 方法
@Autowired(required=false),传递的参数不是必须的 - @Configuration 和 @Bean等同于下面的 XML 配置:
<beans>
<bean id="helloWorld" class="com.tutorialspoint.HelloWorld" /> </beans>
- @import 注解从另一个配置类中加载 @Bean
- @Scope指定Bean的作用域,默认为singleton
- 定位Spring配置文件
@ContextConfiguration("classpath:applicationContext.xml")
- 开启包扫描:
<context:component-scan base-package="com.how2java.pojo"/>
- 类加上@Component注解,即表明此类是bean
@Component("p")
public class Product {
等同于
<bean name="p" class="com.how2java.pojo.Product"><bean/>
- 开启IOC注解:
<context:annotation-config/>
- 在一个类中引用另一个类的属性@Autowired
@Autowired
private Category category;
等同于
<property name="category" ref="c" />
AOP:<aop:aspectj-autoproxy/>
- @AspectJ作用在类上,声明切面(静态代理)
- @Pointcut作用在方法上,声明一个切入点
<aop:aspectj-autoproxy/>
开启AOP注解- @Aspect 表示这是一个切面(声明在日志,事务,统计的类上)
@Around(value = "execution(* com.how2java.service.ProductService.*(..))")
表示对com.how2java.service.ProductService 这个类中的所有方法进行切面操作(声明在类中的方法上)
3.事务
spring支持编程式事务和声明式事务
特性:
- A 原子性(Atomicity) 事务是数据库的逻辑工作单元,事务中的操作要么都不做,要么就全做。
- C:一致性(Consistency) 事务执行的结果必须是从数据库从一个一致性状态转换到另一个一致性状态,一致性是相对而言的。
- I:隔离性(Isolation) 一个事务的执行不能被其他事务干扰
- D:持久性(Durability) 一个事务一旦提交,它对数据库中数据的改变就应该是永久性的
并发问题
- 脏读:(查询)事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
- 不可重复读:(修改)事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
- 幻读:(增加、删除操作)事务A首先根据条件索引得到N条数据,然后事务B改变了这N条数据之外的M条或者增添了M条符合事务A搜索条件的数据,导致事务A再次搜索发现有N+M条数据了,就产生了幻读。
传播行为:
编程式事务管理:
TransactionTemplate和PlatformTransactionManager