目录
3. Data Access/Integration(数据访问/集成)
三. Inversion of Control(IOC)、Dependency Injection(DI)
一.Spring 体系结构
Spring体系结构图
1.Core Container(核心容器)
Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 Expression Language表达式语言模块组成.
- Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。
- Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IOC(控制反转) 和 DI (依赖注入)功能。
- Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。
- Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。
2. Web 模块
Spring 的 Web 层包括 Web、Servlet、Struts 和 Portlet 组件.
- Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IoC 容器初始化以及 Web 应用上下文。
- Servlet模块:包括 Spring 模型—视图—控制器(MVC)实现 Web 应用程序。
- Struts 模块:包含支持类内的 Spring 应用程序,集成了经典的 Struts Web 层。
- Portlet 模块:提供了在 Portlet 环境中使用 MVC实现,类似 Web-Servlet 模块的功能。
3. Data Access/Integration(数据访问/集成)
数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块.
- JDBC 模块:提供了一个 JDBC 的抽象层,大幅度减少了在开发过程中对数据库操作的编码。
- ORM 模块:对流行的对象关系映射 API,包括 JPA、JDO、Hibernate 和 iBatis 提供了的集成层。
- OXM 模块:提供了一个支持对象/XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。
- JMS 模块:指 Java 消息服务,包含的功能为生产和消费的信息。
- Transactions 事务模块:支持编程和声明式事务管理实现特殊接口类
4. 其他模块
Spring的其他模块还有 AOP、Aspects、Instrumentation 以及 Test 模块.
- AOP 模块:提供了面向切面编程实现,允许定义方法拦截器和切入点,将代码按照功能进行分离,以降低耦合性。
- Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。
- Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
- Test 模块:支持 Spring 组件,使用 JUnit 或 TestNG 框架的测试。
二. Spring IoC容器
IoC容器主要作用就是创建并管理Bean对象以及Bean属性注入
1.BeanFactory
是Spring里面最低层的接口,提供了最简单的容器的功能,只提供了实例化对象和拿对象的功能 ;
2.ApplicationContext (应用上下文)
继承BeanFactory接口,它是Spring的一各更高级的容器,提供了更多的有用的功能
1) 国际化(MessageSource)
2) 访问资源,如URL和文件(ResourceLoader)
3) 载入多个(有继承关系)上下文 ,使得每一个上下文都专注于一个特定的层次,比如应用的web层
4) 消息发送、响应机制(ApplicationEventPublisher)
ApplicationContext的实现类:
FileSystemXmlApplicationContext :
从一个 XML 文件中加载 beans 的定义,XML Bean 配置文件的全 路径名必须提供给它的构造函数。
3.两者的区别
加载机制不同:
- BeanFactory使用懒加载机制,当需要使用到bean 的时候才会加载装配,所以启动时间快;如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean()方法才会抛出异常;
- ApplicationContext它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误,这样有利于检查所依赖属性是否注入。 ApplicationContext启动后预载入所有的单实例Bean,通过预载入单实bean,确保当你需要的时候,你就不用等待,因为它们已经创建好了。
优缺点:
- BeanFactory的加载机制导致开发者无法及时发现问题,但启动过程快。
- ApplicationContext能够令开发者及时发现存在的问题,但如果容器过多,会导致启动速度较慢。
三. Inversion of Control(IOC)、Dependency Injection(DI)
IOC和DI不是编程技术,而是一种编程思想。
1.IOC(控制反转)
将对象实例的控制权转给程序,通俗的理解是:平常我们 new 一个实例,这个实例的控制权是我们程序员,而控制反转是指new 实 例工作不由我们程序员来做而是交给 spring 容器来做。
借用Iteye的开涛对IOC的讲解:
●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;
而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制
什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
●为何是反转,哪些方面反转了;有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,
也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,
对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
2.DI(依赖注入)
IOC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI来实现的
依赖注入和控制反转含义相同,它们是从两个角度描述的同一个概念。
Spring 容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者。
调用者通过 Spring 容器获得被调用者实例,这称为依赖注入;
借用Iteye的开涛对DI的讲解:
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
●谁依赖于谁:应用程序依赖于IOC容器;
●为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源;
●谁注入谁:IOC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:注入某个对象所需要的外部资源(包括对象、资源、常量数据)
3.常用依赖注入的方式
1).属性注入setter
2).构造器注入
3).@Autowire注解
四. Spring Bean
1.Bean的作用域
Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域。
1)singleton 单例模式
使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。
单例模式对于无会话状态的 Bean(如 DAO 层、Service 层)来说,是最理想的选择。
2)prototype 原型模式
每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。
对有状态的bean应该使用prototype作用域。有状态对象(Stateful Bean),就是有实例变量的对象
3)request
在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域 仅在当前HTTP Request 内有效。
4)session
在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的session 请求,会返回不同的实例,该作 用域仅在当前 HTTP Session 内有效。
5)global Session
在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。
2.Bean的生命周期
Bean生命周期图
Bean 生命周期的整个执行过程描述如下:
- 根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
- 利用依赖注入完成 Bean 中所有属性值的配置注入。
- 如果 Bean实现了BeanNameAware 接口,则 Spring调用Bean的setBeanName() 方法传入当前Bean的id值。
- 如果 Bean实现了BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
- 如果 Bean实现了ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前ApplicationContext 实例的引用。
- 如果Bean实现了BeanPostProcessor接口,则Spring将调用该接口的预初始化方法postProcessBeforeInitialzation()对Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
- 如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。
- 如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
- 如果BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法postProcessAfterInitialization()此时,Bean 已经可以被应用系统使用了。
- 如果在 <bean> 中指定了该 Bean 的作用范围为 singleton,则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用域为 prototype,则将该Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
- 如果 Bean实现了DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。
五.Spring 注解
1.@Component
可以使用此注解描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。
2.@Repository
用于将数据访问层(DAO层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
3.@Service
通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
4.@Controller
通常作用在控制层,用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
5.@Autowired
用于对 Bean 的属性变量、属性的 Set 方法及构造函数进行标注,配合对应的注解处理器完成 Bean 的自动配置工作。默认按照 Bean 的类型进行装配。
6.@Resource
作用与 Autowired 一样。区别在于 @Autowired 默认按照 Bean 类型装配,@Resource 默认按照 Bean 实例名称进行装配。且@Autowried是spring自带的注解,@Resource是Java自带的注解;
@Resource 中有两个重要属性:name 和 type。
Spring 将 name 属性解析为 Bean 实例名称,type 属性解析为 Bean 实例类型。如果指定 name 属性,则按实例名称进行装 配;如果指定 type 属性,则按 Bean 类型进行装配。
如果都不指定,则先按 Bean 实例名称装配,如果不能匹配,则再按照 Bean 类型进行装配;如果都无法匹配,则抛出 NoSuchBeanDefinitionException 异常。
7.@Qualifier
与 @Autowired 注解配合使用,会将默认的按 Bean 类型装配修改为按 Bean 的实例名称装配,Bean 的实例名称由 @Qualifier 注解的参数指定。
六.Spring AOP
1.概述
1)面向切面编程(AOP)和面向对象编程(OOP)类似,也是一种编程模式
2)它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率
3)借用 Iteye 开涛 讲解:
AOP是一种编程范式,提供从另一个角度来考虑程序结构以完善面向对象编程(OOP)。
AOP为开发者提供了一种描述横切关注点的机制,并能够自动将横切关注点织入到面向对象的软件系统中,从而实 现了横切关注点的模块化。
AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制等,封 装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性
2.相关概念
1).连接点(Joinpoint):
表示需要在程序中插入横切关注点的扩展点,连接点可能是类初始化、方法执行、方法调用、字段调用或处理异常等 等,Spring只支持方法执行连接点,在AOP中表示为“在哪里做”;
2).切入点(Pointcut):
选择一组相关连接点的模式,即可以认为连接点的集合,Spring支持perl5正则表达式和AspectJ切入点模式,Spring默 认使用AspectJ语法,在AOP中表示为“在哪里做的集合”;
3).通知(Advice):或称为增强
在连接点上执行的行为,增强提供了在AOP中需要在切入点所选择的连接点处进行扩展现有行为的手段;包括前置增 强(before advice)、后置增强 (after advice)、环绕增强 (around advice),在Spring中通过代理模式实现AOP,并 通过拦截器模式以环绕连接点的拦截器链织入增强 ;在AOP中表示为“做什么”;
4).方面/切面(Aspect):
横切关注点的模块化,比如上边提到的日志组件类。可以认为是增强、引入和切入点的组合;在Spring中可以使用 Schema和@AspectJ方式进行组织实现;在AOP中表示为“在哪里做和做什么集合”;
5).目标对象(Target Object):
需要被织入横切关注点的对象,即该对象是切入点选择的对象,需要被增强的对象,从而也可称为“被增强对象”; 由于Spring AOP 通过代理模式实现,从而这个对象永远是被代理对象,在AOP中表示为“对谁做”;
6).AOP代理(AOP Proxy):
AOP框架使用代理模式创建的对象,从而实现在连接点处插入增强(即应用切面),就是通过代理来对目标对象应用 切面。在 Spring中,AOP代理可以用JDK动态代理或CGLIB代理实现,而通过拦截器模型应用切面。
7).织入(Weaving):
织入是一个过程,是将切面应用到目标对象从而创建出AOP代理对象的过程,织入可以在编译期、类装载期、运行期 进行。
3.通知的类型
前置通知:在某连接点之前执行的增强,但这个增强不能阻止连接点前的执行(除非它抛出一个异常)。
后置通知:在某连接点正常完成后执行的增强:例如,一个方法没有抛出任何异常,正常返回。
异常通知:在方法抛出异常退出时执行的增强。
返回通知:当某连接点正常返回的时候执行的增强
环绕通知:包围一个连接点的增强,如方法调用。这是最强大的一种增强类型。 环绕增强可以在方法调用前后完成自定
义的行为。它也会选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行。
4.动态代理
1).JDK动态代理
概念:利用拦截器(拦截器必须实现InvocationHanlder)加上反射机制生成一个实现代理接口的匿名类,在调用具体方 法前调用InvokeHandler来处理。
实现步骤:
(1)通过实现InvocationHandler接口来自定义自己的InvocationHandler;
(2)通过Proxy.getProxyClass获得动态代理类;
(3)通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class);
(4)通过构造函数获得代理对象并将自定义的InvocationHandler实例对象传为参数传入;
(5)通过代理对象调用目标方法;
2).CGLIB动态代理
利用ASM开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
3).何时使用JDK还是CGLIB
--如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。
--如果目标对象实现了接口,可以强制使用CGLIB实现AOP。
--如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理和CGLIB之间转换
七:Spring 事务传播行为
事务传播行为类型 | 说明 |
---|---|
* 保证同一个事务中 | |
PROPAGATION_REQUIRED | 支持当前事务,如果当前没有事务,就新建一个事务。[ 默认传播行为 ] |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 支持当前事务,如果当前没有事务,就抛出异常。 |
* 保证不在同一个事务中 | |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则新建事务。 |
推荐文章:
JDK动态代理:https://blog.youkuaiyun.com/yhl_jxy/article/details/80586785
CHLIB动态代理:https://blog.youkuaiyun.com/yhl_jxy/article/details/80633194