本文是根据JavaGuide的总结复习
IOC控制反转,其实是设计模式中的依赖倒置思想的实现,将原本在程序中手动创建对象的控制权交给Spring框架来管理。
依赖注入:把底层类作为参数传入上层类,实现上层类对下层类的“控制”。
图片于来源:网络
(1)首先通过ClassPathXmlApplicationContext
获取到所提供的资源文件路径,处理成配置文件数组
(2)调用Refresh
方法进行容器的重建。Refresh
会将原本的Applicationontext
销毁。
(3)在Refresh
方法中:
prepareRefrash()
方法。记录启动时间,校验xml文件。obtainFreshBeanFactory()
方法。在这个方法中会进行初始化BeanFactory
,加载Bean
,注册Bean
**等工作。但是在这里Bean实例
还没有被创建。
ApplicationContext
继承自BeanFactory
,但是它不应该被理解为 BeanFactory 的实现类
,而是说其内部持有一个实例化的
BeanFactory(DefaultListableBeanFactory
)。以后所有的 BeanFactory 相关的操作其实是委托给这个DefaultListableBeanFactory
实例来处理的。
从代码层面来讲,就是接口BeanDefinition
的实例。
AOP就是面向切面编程的意思,能够将那些与业务无关,却为业务模块所共同调用的逻辑和责任封装起来。(如:事务处理,日志管理,权限控制等)。便于减少代码重复,降低模块的耦合度,利于扩展性和可维护性。
SpringAOP基于动态代理。
- 如果实现了某个接口,那么SpringAOP使用JDK Proxy去创建代理对象。
- 如果没有实现接口的对象,使用Cglib去生产一个代理对象的子类作为代理。
- 也可以使用AspectJ。AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了
单例Bean是存在线程安全问题的。当多个线程操作同一个对象的非静态成员变量时,就会产生线程安全问题。
解决方法:使用ThreadLocal定义成员变量。
MVC是一种设计模式,Spring MVC是Spring框架对于MVC模式的运用。SpringMVC主要用于帮助我们进行web开发。MVC模式下,将后端分为了Service层处理业务,Dao层数据库操作,Entity层实体类,Controller层,返回数据给前台。
DispatcherServlet
HandlerMapping
,解析请求对应的Handler
。andlerAdapter
,适配器来进行处理。真正的处理器
处理请求,和相应的逻辑业务。ModelandView对象
,Model返回数据对象,View是逻辑上的View。并不是真正展示的视图ViewResolver
根据返回的View查找实际的View。
工厂模式:
Spring使用工厂模式可以通过 BeanFactory 或 ApplicationContext 创建 bean 对象。
BeanFactory:延迟注入,使用到某个bean的时候才会进行创建。
ApplicationContext:容器启动时,一次性全部创建bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
// 检查缓存中是否存在实例
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
//...省略了很多代码
try {
singletonObject = singletonFactory.getObject();
}
//...省略了很多代码
// 如果实例对象在不存在,我们注册到单例注册表中。
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
//将对象添加到单例注册表
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
}
}
}
代理模式
SpringAOP就是基于代理模式的。
如果代理对象实现了某个接口就是用JDK Proxy去创建代理对象。
如果代理对象没有实现某个接口,就会使用Cglib去生成一个被代理对象实例来进行代理。
Spring中的代理也可以使用AspectJ进行,Spring集成了AspectJ。当切面多的时候就可以使用它。
模板方法
:是一种行为设计模式,它定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
在Spring中的模板方法使用主要是体现在以Template结尾的数据库操作类中,如JDBCTemplate,HiberbateTemplate
但Spring中对于模板方法模式进行了改进,一般的模板方法都是使用的子类去实现一个操作,而Spring中则是采用Callback模式(回调模式)和模板方法配合使用。
Callback模式(回调模式):把工作流内的某个功能,按照约定的接口暴露给外部使用者,为外部使用者提供数据,或要求外部使用者提供数据。
观察者模式
:是一种对象行为型模式。它表示的是一种对象与对象之间具有依赖关系,当一个对象发生改变的时候,这个对象所依赖的对象也会做出反应。
Spring中的事件驱动模型就是用来这个设计模式。
Spring事件执行流程如下:
(1) 定义一个事件: 实现一个继承自 ApplicationEvent
,并且写相应的构造函数;
(2)定义一个事件监听者:实现 ApplicationListener 接口
,重写 onApplicationEvent() 方法
;
(3)使用事件发布者发布消息: 可以通过ApplicationEventPublisher 的 publishEvent() 方法发布消息
。
适配器模式
:适配器模式(Adapter Pattern) 将一个接口转换成客户希望的另一个接口,适配器模式使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。
SpringAOP的增强或者通知都使用了适配器模式,相关的接口:AdvisorAdapter。
Spring预定义的通知要通过对应的适配器,适配成 MethodInterceptor接口(方法拦截器)类型的对象(如:MethodBeforeAdviceInterceptor 负责适配 MethodBeforeAdvice)。
SpringMVC中的适配器模式:
DispatcherServlet 根据请求信息调用 HandlerMapping,解析请求对应的 Handler。解析到对应的 Handler(也就是我们平常说的 Controller 控制器)后,开始由HandlerAdapter 适配器处理。
-
装饰者模式(包装器模式)
:动态地给对象添加一些额外的属性或行为
Spring 中配置 DataSource 的时候,DataSource 可能是不同的数据库和数据源。这个时候就要用到装饰者模式(这一点我自己还没太理解具体原理)。Spring 中用到的包装器模式在类名上含有 Wrapper或者 Decorator。这些类基本上都是动态地给一个对象添加额外的职责。
声明式事务分为:
XML
注解
TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.
TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
TransactionDefinition.PROPAGATION_REQUIRED(propagation required): 如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
TransactionDefinition.PROPAGATION_SUPPORTS(propagation supports): 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_MANDATORY(propagation mandatory): 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)
TransactionDefinition.PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。创建一个新的事务
当@Transactional注解作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。
在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚。
JPA(java persistence API)用于管理JavaEE和JavaSE环境中的持久化,以及对象/关系映射的JavaAPI
是处理数据持久化的一个接口,规范
- 实体(pojo)表示关系数据库中的一个表
- 每个实体实例对应着该表中的一行
- 类必须用javax.persistence.Entity注解
类必须含有一个public或者protected的无参构造函数- 当实体实例被当做值以分离对象的方式进行传递(例如通过会话bean的远程业务接口)则该类必须实现Serializable(序列化)接口
- 唯一的对象标志符,简单主键(javax.persistence.Id),复合主键(javax.persistence.EmbeddledId和javax.persistence.IdClass)