Spring基础
spring可以实现很多功能,但是在日常项目开发过程中最常用到的还是依赖注入DI和面向切面编程AOP,其实spring最根本的目的就是简化代码开发。
如果你在spring之前接触过java开发,你会发现很多框架会强迫应用继承他们的类或实现他们的接口从而让应用和框架进行绑死,而Spring不会强迫你实现Spring的一些接口或者集成Spring规范的类,通常我们在使用Spring的时候没有任何痕迹说明你使用了Spring,除了注解。
spring框架本身的四大原则:
- 使用pojo进行轻量级及最小侵入式开发。
- 通过依赖注入和基于接口编程实现松耦合。
- 通过aop和默认习惯进行声明式编程。
- 使用aop和模板开发减少模块化代码。
最小侵入式开发:
我们常说的控制反转和依赖注入在spring环境下是等同的概念,控制反转是通过依赖注入实现的,所谓的依赖注入是指由容器来负责创建对象和维护对象之间的依赖关系,而不是通过对象本身负责自己的创建和解决自己的依赖。依赖注入主要是为了解耦,体现组合的概念。当你需要某个类具有某种功能,在继承某个具有此功能的类和组合具有此功能的类时,本着低耦合的概念当然是选择组合该类。
声明式编程
容器在进行bean的管理时,首先需要通过xml、注解或Java配置来声明该类需要交给容器管理,然后通过注解实现类的注入。
声明Bean的注解:
- @Component组件
- @Service 业务逻辑层使用
- @repository数据访问层使用
- @Controller在展现控制层使用
注入Bean的注解:
- @Autowire :spring提供
- @Inject:JSR-330提供
- @Resource:JSR-250提供
@Autowire、@Inject、@Resource可以使用在set方法或属性上。
AOP面向切面编程
springAop面向切面编程可以使一组类共享相同的行为。相比继承和实现接口来说,aop耦合性更低,aop的目的便是降低耦合性。
spring支持aspectJ的注解式切面编程。使用时需要手动开启spring对aspectJ的支持。
- 使用@aspect声明切面。
- 使用@After、@Before、@Around定义建言(advice),可以将拦截规则(切点)作为参数。若要实现切点的复用,则使用@PointCut专门定义拦截规则。调用该切点。
- 每一个被拦截处都称为一个拦截点。
Spring常用配置
Bean的Scope
Scope描述容器如何创建新Bean,通过在Bean上添加@Scope注解实现.
- Singleton:默认,单实例,全容器共享一个实例。
- Prototype:每次调用新建一个bean实例.
- Request:Web项目中每一个http request建立一个新实例。
- Session:Web项目中每一个http session新建一个实例。
- GlobalSession:只在portal应用中有用,每一个global http session新建一个实例。
Bean的初始化和销毁
- java配置方式:使用@Bean的initMethod和destroyMethod(相当于xml配置的init-method和destory-method)
- 注解方式:利用JSP-250的@PostConstruct和@PreDestroy
Spring El
通过在属性上添加注解@Value使用
- 注入普通字符串。@Value("")
- 注入操作系统属性。@Value("#{systemProperties[‘os.name’]}")
- 注入表达式运算结果.@Value("#{…}")
- 注入其他bean属性.@Value("#{*.*}")
- 注入文件内容。@Value(“文件路径”) Resource类型
- 注入网址内容。@Value(“网址url”) Resource类型
- 注入属性文件。@Value("${}")
Profile
个人理解,相当于组。
通过@Profile(“”)来为Bean标记分组,通过environment的activeProfiles来设定当前context需要使用的配置环境(换种说法,设定当前context需要使用的某个组的bean)。
Application Event事件
Spring的事件为Bean与Bean之间的消息通信提供支持。若我们需要一个Bean处理完事件以后,另一个Bean也能做出相应的处理,那么我们就需要第二个Bean监听第一个Bean。
Spring 事件的流程
- 自定义事件,继承applicationEvent。
- 定义事件监听器,实现ApplicationListener。
- 使用容器发布事件。
Spring Aware
Spring依赖注入的最大亮点就是你的Bean对Spring容器的存在是没有意识的,你可以毫无声息的将你的容器换成别的容器。但是在实际项目中,有时候你需要使用spring容器本身的资源,那么Bean本身就要意识到容器的存在,这就是Spring ware,但是需要注意的是Spring ware会使Bean与框架耦合。
Spring Aware的目的是让Bean获得Spring容器的服务,因为applicationContext接口实现了MessageSource接口、ApplicationEventPublisher接口和ResourceLoader接口,所以Bean继承ApplicationContextAware可以获得Spring容器的所有服务,但是我们不推荐这么做,原则上还是我们需要什么就实现什么接口。
Spring提供的aware接口
接口名 | 作用 |
BeanNameAware | 获得容器中Bean的名称 |
BeanFactoryAware | 获得当前Beanfactory,可调用容器服务 |
ApplicationContextAware | 当前的applicationContext,调用当前服务 |
MessageSourceAware | 获得message source,可以获取文本信息 |
ApplicationEventPublisherAware | 应用事件发布器 |
ResourceLoaderAware | 获取资源加载器,获取外部资源文件 |
多线程
spring是通过任务执行器(TaskExecutor)来实现多线程和并发编程的,使用ThreadPoolTaskExecutor实现基于线程池的TaskExecutor。若是要使用异步任务的话则需要在配置类里通过@EnableAsync开启对异步任务的支持,并通过在Bean上使用@Async注解来声明该任务是个异步任务。多线程异步配置类要实现AsyncConfigurer接口来重写getAsyncExecutor获取基于线程池的多线程执行器。
注:多线程一般都是通过线程池来实现。异步执行的意思是主线程只管发起,不管过程和结果。
计划任务
spring的计划任务需要在配置类通过@EnableScheduling开启对计划任务的支持,然后在执行计划任务的方法上添加注解@Scheduled,声明该任务是个计划任务。
@Scheduled参数详解
1、corn周期性执行
corn表达式
[秒] [分] [时] [日] [月] [周] [年]
注:每个域之间以空格间隔,[年]不是必须的域,可以省略[年],则一共6个域,
说明 | 必填 | 允许值 | 可用的通配符 |
秒 | 是 | 0-59 | , - * / |
分 | 是 | 0-59 | , - * / |
时 | 是 | 0-23 | , - * / |
日 | 是 | 1-31 | , - * / L |
月 | 是 | 1-12或JAN-DEC | , - * ? / W |
周 | 是 | 1-7或SUN-SAT | , - * ? / L # |
年 | 否 | 1970-2099 | , - * / |
通配符说明:
- *表示所有值。例如:在分上设置*,表示每一分钟都触发。
- ?表示不指定值。例如每月10号触发,不关心是周几,则0 0 0 10 * ?
- -表示区间。例如,在小时上设置 10-12,表示10,11,12点都会触发。
- ,表示多个值。例如在周上设置 MON,WED,FRI ,表示周一,周三和周五触发
- 、用于递增触发。例如在秒上设置5/15,表示从5秒开始,每隔15秒触发(5,20,35,50)。
- L表示最后。例如在周上设置6L,表示本月最后一个周五
- W表示离指定日期最近的工作周。例如在日上设置15W,表示每月15号最近的那个工作日
- #序号(表示每月的第几个周几)。例如在周字段设置6#3,表示每月第三个周六。
2、zone
时区,接收一个java.util.TimeZone。默认为空字符串,即取服务器所在地的时区。
3、fixedDelay
上次执行完毕的时间点后多长时间再执行。
@Scheduled(fixedDelay = 5000) //上次执行完毕时间点后5秒在执行
4、fixedDelayString
与3等同,不过使用的是字符串,并且支持占位符。
@Scheduled(fixedDelayString = “5000”) //上次执行完毕时间点后5秒在执行
@Scheduled(fixedDelayString = "${time.fixedDelay}")
5、fixedRate
上一次开始执行时间点之后多长时间在执行。
@Scheduled(fixeRate = 5000) //上一次开始执行时间点之后每5秒执行
6、fixedRateString
与5相同,使用字符串,支持占位符。
7、initialDelay
第一次延迟多长时间后在执行。
@Scheduled(initialDelay=1000,fixedRate=5000) //第一次延迟1秒执行,之后每5秒执行一次
8、initialDelayString
与7相同,使用字符串,支持占位符。
条件注解@Conditional
1、条件类需要实现Condition接口,重写matches方法。
2、在配置类中的Bean上添加条件注解@Conditional(),若是在配置类上添加条件注解,那么若符合条件则批量创建该配置类中的所有Bean,若不符合条件则所有Bean都不创建
Spring Test测试
Spring通过Spring TestContextFramework对集成测试提供顶级支持。不依赖于特定的测试框架。
Spring 提供了一个SpringJUnit4ClassRunner类,它提供了Spring TestContext Framework的功能。通过@ContextConfiguration来配置Application Context。