Spring
# 介绍
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
# 作用
◆目的:解决企业应用开发的复杂性
◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能
◆范围:任何Java应用
Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架。
# Spring的核心
Spring的核心是ioc和aop,ioc是控制反转、aop是面向切面编程、ioc降低了耦合度;可以把依赖关系注入到配置文件中,使用配置文件进行注入或使用@Bean。aop是面向切面可以做方法的的前置增强、后置增强、添加日志或者事务
# IOC
IoC 全称为 Inversion of Control,翻译为 “控制反转”,它还有一个别名为 DI(Dependency Injection),即依赖注入。
Ioc是一种面向对象思想,从原先应用主动获取改为ioc为应用创建不再需要自己去创建,只需把你要需要创建的东西交给ioc由ioc来创建,等应用程序需要的时候告诉ioc,ioc再给应用程序,从而实现降低应用程序中的耦合度,也从主动行为改成了被动行为创建对象交给ioc容器处理,控制颠倒过来了,这也是控制反转的由来。
依赖注入是ioc容器运行期间,动态获取依赖关系进行注入到对象中;依赖注入和控制反转是从不同的角度描述的同一件事情,指通过引入Ioc容器,利用依赖关系注入方式,实现对象之间的解耦。
# IOC原理
ioc容器通过java的反射机制+xml配置文件,当web容器(tomcat)启动的时候全局bean会去xml中的配置文件中查找需要扫描的包下的所有类,并根据使用的注解,进行封装成全局的bean容器中进行管理,初始化完成之后bean的容器,bean的id以及bean实例化的对象的信息会存在于容器中,在service中调用另一个beanid可以获取到bean的详情信息,如果bean存在会返回该bean的实例。
# Bean定义
在Spring中,那些组成应用程序的主体由Spring IOC容器所管理的对象,被称为bean。Bean是由ioc容器初始化、装配及管理的对象,初次之外,bean就与应用程序中的其他对象没有任何区别了。
# 创建bean
这里介绍三种常见的创建方式:自动装配、Bena、xml来创建如下:
方式一:
使用@Component来创建bean,该注解可以传一个参数value,用来指定要创建的bean的名称,默认使用类名并且首字母小写。 以下代码演示了如何使用@Component创建一个bean:
@Component
public class SuperObject {
public void method(){
//Business
}
}
@Component
public class SonObject implements SuperObject{
@Override
public void method(){
//Business
}
}
方式二:
通过@Configuration、@Bean注解来实现
@Configuration
public class ObjectConfig {
@Bean
public void method(){
//Business
}
}
方式三:
通过xml进行实现,首先创建一个
@Configuration
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="method" class="com.java.config"/>
</beans>
}
# Bena 作用域
类别 | 说明 |
---|---|
singleton | 在Spring IoC容器中仅存在一个Bean实例,Bean以单例方式存在,默认值 |
prototype | 每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时,相当于执行new XxxBean() |
request | 每次HTTP请求都会创建一个新的Bean,该该作用域仅适用于WebApplicationContext环境 |
session | 同一个HTTP Session共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext环境 |
globalSession | 一般用于Portlet应用环境,该作用域仅适用于WebApplicationContext环境 |
Bean的五种作用域中,request、session和globalSession 三种作用域只在基于web的应用中使用(不必关心所采用的是什么web应用框架),只能用在基于 web 的 Spring ApplicationContext 环境。
# 怎么设置作用域
以singleton为例
singleton唯一 bean 实例,当一个 bean 的作用域为 singleton,那么Spring IoC容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回bean的同一实例。
singleton 是单例类型(对应于单例模式),就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,但我们可以指定Bean节点的 lazy-init=”true” 来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化。 每次获取到的对象都是同一个对象。注意,singleton 作用域是Spring中的缺省作用域。要在XML中将 bean 定义成 singleton 。
可以这样配置:
<bean id="ServiceImpl" class="cn.csdn.service.ServiceImpl" scope="singleton">
也可以通过 @Scope 注解(它可以显示指定bean的作用范围。)的方式
@Service
@Scope("singleton")
public class ServiceImpl{
//Business
}
# bean的生命周期
Spring Bean是Spring应用中最最重要的部分了。所以来看看Spring容器在初始化一个bean的时候会做那些事情,顺序是怎样的,在容器关闭的时候,又会做哪些事情。
1、Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
2、Bean实例化后对将Bean的引入和值注入到Bean的属性中
3、如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
4、如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
5、如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
6、如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
7、如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
8、如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
9、如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。
# AOP
AOP是Spring框架面向切面的编程思想,AOP采用一种称为"横切"的技术,将涉及多业务流程的通用功能抽取并单独封装形成独立切面,在合适的时机将这些切面横向切入到业务流程指定的位置中。
# AOP原理
AOP采用是JVM中的动态代理机制,动态代理分为CGLib、JDK,什么是动态代理?简单理解一下,程序运行时由Java反射机制动态生成动态代理,不需要手动编写它的源代码,可以简化编程工作。采用了Java中最常见的设计模式代理模式。什么是代理模式呢?用一个经典的案例来解说一下:假如有一辆正在行驶的汽车,有一天司机突然想记录一下今天行驶的时间这个时候就用到了代理模式,首先把正在行驶的汽车作为目标方法,代理目标方法在开始行驶时记录一个当前时间,在结束行驶时记录一个结束时间,最后用结束时间减去开始时间;这个过程称为代理模式。
# Spring常用注解
# 组件注解
在SpringIOC运行容器中,是通过core建立维护各个Bean之间的关系,也是我们说的,组件注册
注解名称 | 说明 |
---|---|
@Component | 用于标注一个普通的bean,指定某个类是容器的bean。 |
@Controller | 用于标注一个控制器类(控制层 controller)。 |
@Service | 用于标注业务逻辑类(业务逻辑层 service)。 |
@Repository | 用于标注DAO数据访问类 (数据访问层 dao)。 |
@Scope | 注解和@Component类注解联合使用,用于标记该类的作用域,默认singleton。 |
@Lazy(true) | 指定初始化顺序,是否延迟。 |
@DepondsOn | 强制初始化。(使用@DepondsOn("xxx")会先初始化双引号中的bean。 |
@Resource | 用来装配bean,和@Autowired的功能一样,不同的是@Resource是通过byName获取的Bean。 |
@Autowired | 同@Resource功能一样,用来装配bean,不同的是@Autowired是通过byType |
# 配置相关注解
注解名称 | 说明 |
---|---|
@Bean | 注入一个bean,通常和Configuration一起使用,将方法注入到容器中。 |
@ConfigurationProperties | 用于读取配置文件,可以获取到配置文件中的属性值。 |
@Configuration | 用于修饰一个类,代表该类数据配置类,相等于Bean的xml文件。 |
@Import | 该注解用于一般不在扫描包下的配置类,进行引入配置类时使用。 |
@ImportResource | 修饰Java类,用于向类引入xml配置文件。 |
@Value | 可以读取配置文件,用于注入对象属性,或常量时使用。(注:在static修饰词上使用无效。) |
@PropertySource | 一般用于加载属性文件,可以使用Value来加载文件路径。 |
# 切面相关注解(AOP相关注解)
注解名称 | 说明 |
---|---|
@Aspect | 用来定义切入点,修改Java类,用@Aspect修饰过的类,容器不会对该类进行增强。 |
@Before | 用Before修改过的方法可以对目标方法进行前置增强。 |
@AfterReturning | 后置增强,用AfterReturning修饰过的方法,会等目标方法正常返回后进行后置增强。用来修饰方法用。 |
@AfterThrowing | 异常增强,当目标方法抛出异常之后无法捕获的时候进行对目标方法增强。(修饰方法。) |
@After | 同AfterReturning相同,做后置增强,不同的是After不管目标方法有没有正常返回都会对目标方法进行后置增强。 |
@Around | 用来修饰方法,可以对目标方法进行前置、后置增强,决定目标方法什么时候执行。(一般在线程安全情况下使用) |
@Pointcut | 定义一个切入点表达式用于被其他增强调用。使用该方式定义切入点方便管理,易复用。 |
# 本文Demo下载地址
https://github.com/superman-yuan/SpringDemo.git
# 总结
Spring给复杂的J2EE开发带来了春天。它的核心是轻量级的IoC容器,它的目标是为J2EE应用提供了全方位的整合框架,在Spring框架下实现多个子框架的组合,这些子框架之间可以彼此独立,也可以使用其它的框架方案加以代替,Spring希望为企业应用提供一站式(one-stopshop)的解决方案。