Spring基础
Spring基本概念
spring是一个轻量级的开源框架,提供了以前EJB才能提供的企业级服务,为java应用程序的开发提供了综合,广泛的基础性支持,帮助开发者解决了开发中基础性的问题,专注于应用程序的开发,降低了开发的复杂性,核心:AOP(面向切面编程)和IOC(控制反转),框架的核心功能可用于开发任何的Java应用程序
优点:
- Spring通过控制反转,实现了面向接口编程,降低系统的耦合性
- Spring容器可以管理所有托管对象的生命周期和维护他们的依赖关系,开发人员可以无须关心对象的创建和维护,专注于程序的开发
- Spring提供面向切片编程,便于将主要逻辑和次要逻辑分开,将通用业务从业务系统中分离开来
- 可以只用简单的注解配置完成对数据库事务的处理
- Spring不重复发明轮子,而是提供对各种优秀框架的整合,无缝集成框架,降低开发者使用这些框架的复杂度
- 对于Java EE开发中难用的API,都提供了封装,使用这些API的难度大大降低
- Spring采用模块化设计,模块之间相互解耦,出核心模块外,开发者可以根据需要选择其他任意模块
- Spring框架的轻量级和非入侵性,也具有高度开放性,所以并不强求应用完全依赖于Spring,开发者可以部分或全部依赖Spring框架
- Spring的DAO模块提供了一致的异常处理结构层,简化了对数据库的操作
IOC
控制反转(IOC),是面向对象编程中的一种设计原则,用来减少系统之间的耦合度。控制反转指的是将控制权从应用程序转移到框架,在Spring中将控制权转移到IOC容器,
public class Car{
private Wheel mWheel = new Wheel();
}
引入IOC之后,控制权由Car对象转移到了IOC容器,Wheel对象由IOC容器来创建,
public class Car{
private Wheel mWheel;
@Autowired
public void setWheel(Wheel wheel){
this.mWheel = wheel;
}
}
Wheel可以设计成为一个接口,然后在运行的时候指定实现类,当Wheel的业务有修改的时候,可以修改关于Wheel的配置,而不会影响Car的代码
此刻,我也可以看出IOC的好处,程序员无需关心对象的的创建和维护它们之间的关系,只要做好相关的配置,IOC容器就会负责管理,我们只需要关心业务逻辑的实现
面向接口编程:
在调用类(类必须要IOC容器维护),只需要声明一个接口和变量,IOC容器将会注入类所需要的实例,业务层和业务系统之间只需要通过接口来向外暴露功能,降低了系统内部的耦合性。
采用IOC机制,能提高系统的可拓展性,如果程序之间提供可显的调用进行交互作用,将会使得程序之间的连接十分紧密,当其中一方要进行更改的时候,会使得程序进行较大的改动,这往往是我们不愿意看到的
例如:
要为一家农户卖水果,假设农户刚开始只卖苹果,那么随着后面的扩展,肯定会有更多的水果涌入,未来随时可能改变水果的类型,例如:香蕉,樱桃等等……,传统的实现方式,会针对水果进行抽象化为一个基类,拓展器子类,苹果和其他水果只需要继承就好
我们来看一下传统书写有哪些缺点
首先,这种方法是可以满足当前的设计要求的,但是方法的可拓展性不好,存在不恰当的地方,例如:当农户发现苹果的销量不好的时候,决定卖香蕉,只需要让banana继承自fruit基类即可,但是,在系统中要修改的地方可不少,Fruit f = new apple ()的地方都要改为Fruit f = new banana(),这种改动量就非常大了
下面我们主要介绍Spring框架中采用的IOC后实现的方法,如:
Spring容器将会根据配置文件来创建调用对象(Sale),同时把被调用的对象(Fruit的子类)的实例化对象通过构造函数或set方法的形式注入调用者对象中
== 具体而言 ==
优点:
- 通过IOC容器,开发任意不需要关注对象是任何被创建的,同时增加新的类也非常方便,需要修改配置文件即可,即实现对象的热插拔
- IOC容器可以通过配置文件来确定需要注入的实例化对象,因此非常便于进行单元测试
缺点:
- 对象的创建是通过反射机制实例化出来的,因此对系统的性能会有一定的影响
- 创建对象的流程变得比较复杂
AOP
AOP即是面向切面编程的思想,把功能分为核心业务和周边业务,在添加周边业务的时候要尽量避免影响周边业务功能,例如:增删改查是核心业务功能,查日志,报告是周边业新的日志的时候就应该避免取影响核心的业务功能
概念
切入点:在哪些类和方法上切入
增强/通知:定义在方法执行的时候实际做什么
织入:将增强/通知添加到目标类的具体连接点上的过程
切面:切面由切点和增强/通知组成,
SpringAOP是通过代理来实现的,代理模式就是一种设计模式,它提供了对目标对象的额外访问方式,即通过代理对象来间接访问目标对象,这样就可以不修改原来对象的前提下,提供额外的访问方式,拓展目标对象功能,简单来说AOP代理模式就是通过一个中间件来访问原目标对象,以达到增强原对象的功能和简化方式SpringAOP代理的实现方式主要有俩种:
- 静态代理
静态编译在编译时就已经实现,编译完成后代理类实际上是一个class文件 - 动态代理
在运行JVM中动态生成的,即编译完成没有实际的class文件,而是在运行动态生成类字节码,并加载到JVM中
AOP注解
Spring2.0之后提供了注解配置AOP的方式,开启的方式是在XML中配置
(1)Before:在目标方法被调用之前做增强处理,@Before只需要指定切入点表达式即可
(2)AfterReturning:在目标方法正常完成后做增强,@AfterReturning除了指定切入点表达式后,还可以指定一个返回值形参名returning,代表目标方法的返回值
(3)AfterThrowing:主要用来处理程序中未处理的异常,@AfterThrowing除了指定切入点表达式后,还可以指定一个throwing的返回值形参名,可以通过该形参名来访问目标方法中所抛出的异常对象
(4)After:在目标方法完成之后做增强,无论目标方法时候成功完成。@After可以指定一个切入点表达式
(5)Around:环绕通知,在目标方法完成前后做增强处理,环绕通知是最重要的通知类型,像事务,日志等都是环绕通知,注意编程中核心是一个ProceedingJoinPoint
Spring Bean
Bean是构成用户应用程序的主干的Java对象,由SpringIOC容器管理Bean是基于用户提供给容器的配置元数据的创建,配置,装配,管理,一个Spring Bean的定义包含容器所必须的所有配置元数据,包括如何创建一个Bean,它的生命周期详细及它的依赖
-
作用域:
Spring支持5种作用域,SingLeton与Prototype是基本作用域,适用于所有Bean,Singleton是Spring默认作用域。Request,Session,GlobalSession是Web作用域,只有在Web应用中使用Spring时,这三个作用域才有效。现分别介绍如下
- Singleton:单例模式,在SpringIOC容器中,使用Singleton作用域的Bean将只有一个实例
- Prototype:原型模式,每次注入,SpringIOC容器将创建一个新的实例,即每次Http请求将会产生不同的Bean实例
- Request:对应每次Http请求,使用Request作用域的Bean都会创建一个新实例,即每次Http请求将产生不同的Bean实例
- Session:对应每次HttpSession,使用Session作用域的Bean都会创建一个新的实例
- Global Session:同一个全局的HttpSession,只会创建一个新实例,典型情况下,仅在使用portlet context的时候有效
比较常用的是Singleton和Prototype这俩个作用域,Spring默认使用Singleton作用域,容器会管理Bean的整个生命周期。而使用prototype作用域时,容器创建实例交给调用组件后,将不再管理维护该实例,使用Singleton作为作用域的好吃,是可以节省频繁创建与销毁实例的开销。**注意:**单例情况下,Bean不是线程安全的
-
生命周期:
SpringBean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点,简单概括为以下的步骤:
- 实例化
- 属性填充
- 三种方式初始化
- 处理Awar接口
- BeanPostProcessor子接口的处理,如AutowiredAnnotationBeanPostProcessor扫描@autowired注解,完成自动注入
- 处理各种后置处理器,在初始化方法后的后置方法中会根据情况包装为代理类,即AOP
- 销毁
Spring注解
Spring常用的注解可以简单分为组件类注解,装配Bean注解和配置类注解
**组件类注解:**作用在类或者方法上,用来标识需要的Java类,常用的组件类注解由:
-
@Component:用来标记一个普通的SpringBean类
-
@Repository: 用于标记一个DAO组件类
-
@Service:用来标记一个业务组件类
-
@Controller:用来标识一个业务类组件
装配Bean的注解:@Auto wired和@Resource
**配置类的注解:**作用于类和方法上,可以替代XML的配置,常用的配置类注解有:
- @Configuration:注解在类上,声明当前类为配置类
- @Bean:注解在方法上,声明当前方法的返回值为一个Bean
- @ComponentScan:用于Component进行扫描
- WishlyConfiguration:为@Configuration与@ComponentScan的组合注解,可以替代这俩个注解