SpringBoot 小谈一下Spring基础

1 Spring 基础
1.1 Spring 概述
1.1.1 Spring 的简史
在我的印象中,大学时期就已经有了 Spring ,整天为配置xml而揪头发,想想这些年,真实变化快啊第一阶段: xml 配置
在 Spring 1.x 时代 ,使用 Spring 开发,满眼都是 xml 档案配置的 Bean,随着专案的扩大, 我们需要把 xml 配置档案
分放到不同的配置档案里,那时候需要频繁的在开发的类和配置档案之间切换。
第二阶段: 注解配置
在 Spring 2.x 时代 ,随着 JDK 1.5 带来的注解支援,Spring 提供了宣告 Bean 的注解(如:@Component、@Service),减少了配置量。
第三阶段: Java 配置
从 Spring 3.x 到现在,Spring 提供了 Java 的配置能力,使用 Java 配置让你更容易理解你配置的 Bean,我们目前放好处在这个时代,
Spring 4.x 和 Spring Boot 都推荐使用 Java 配置。
1.1.2 Spring 概述
Spring 框架是一个轻量级的企业级开发的一站式解决方案。所谓解决方案,就是可以基于 Spring 解决 Java EE 的所有问题。Spring 框架主要提供了 IoC 容器、AOP、资料访问、Web 开发、讯息、测试等相关技术的支援。
Spring 使用简单的 POJO (Plain Old Java Object,即无任何限制的普通 Java 物件)来进行企业级开发。每一个被 Spring 管理的
Java 物件都被称为 Bean,而 Spring 提供了一个 IoC 容器用来初始化物件,解决物件间的依赖管理和物件的使用。
Spring 模组 Spring 是模组化的,你可以只用你需要的 Spring 模组。1)核心容器(Core Container)
Spring-Core:核心工具类,Spring 其他模组大量使用 Spring-Core;
Spring-Beans:Spring 定义 Bean 的支援;
Spring-Context:执行时 Spring 容器;
Spring-Context-Support:Spring 对第三包的支援;
Spring-Expression:使用表示式语言在执行时查询和操作物件。
2)AOP
Spring-AOP:基于代理的 AOP 支援;
Spring-Aspects:基于 Aspects 的 AOP 支援;
Spring-Context:执行时 Spring 容器;
Spring-Context-Support:Spring 对第三包的支援;
Spring-Expression:使用表示式语言在执行时查询和操作物件。
3)讯息(Message)
Spring-Message:对讯息架构和协议的支援;
4)Web
Spring-Web:提供基础的 Web 整合功能,在专案中提供 Spring 的容器;
5)资料访问/整合(DataAccess/Integration)
Spring-JDBC:提供以 JDBC 访问数据库的支援;
Spring-TX:提供程式设计式和宣告式的事物支援;
Spring-ORM:提供 物件/关系对映 技术的支援;
Spring-OXM:提供 物件/XML对映 技术的支援;
Spring-JMS:提供对 JMS 的支援;
Spring 的生态 Spring 发展到现在已经不仅仅是 Spring 框架本身的内容, Spring 目前提供了大量的基于 Spring 的专案, 可以用来更深入地降低我们的开发难度,提供开发效率。目前 Spring 的生态里有一下专案:
1)Spring Boot;使用预设开发配置来进行快速开发;
2)Spring XD:用来简化大资料开发;
3)Spring Cloud:为分散式系统开发提供工具集;
4)Spring Data:对主流的关系型、NoSQL 数据库的支援;
5)Spring Integration:通过讯息机制对企业整合模式(EIP)的支援;
6)Spring Batch:简化和优化大量资料的批处理操作;
7)Spring Security:通过认证和授权保护应用;
8)Spring HATEOAS:基于 HATEOAS 原则简化 REST 服务开发;
9)Spring Social:与社交网络API的整合
10)Spring Mobile:提供对手机装置检测的功能
11)Spring For Android:主要提供在 Android 消费 RESTFul API 的功能
12)Spring Web Flow:基于 Spring MVC 提供基于向导流程式的 Web 应用开发
13)Spring Web Services:基于协议有限的 SOAP/Web 服务
14)Spring LDAP:简化使用 LDAP 开发
15)Spring Session:提供一个 API及实现来管理使用者会话资讯
1.2 Spring 专案快速搭建
早期,都是把依赖的 jar 包放到类路径下,以来混乱。为了解决依赖问题,需要专案构建工具。
目前主流的专案构建工具:Ant、Maven、Gradle等。
1.2.1 Maven 简介
1.2.2 Maven 安装
安装测试安装 mvn -v1.2.3 Maven 的 pom.xml
Maven 是基于专案物件模型的概念运作的,所以 Maven 都有一个 pom.xml。dependenciesdependency 元素 groupId、artifactId、version变数定义 properties编译外挂 build -> plugins -> pluginMaven 运作方式 Maven 会自动根据 dependency 中的依赖配置,直接通过互联网在 Maven 中心库下载相关依赖包到 .m2 目录下, .m2 是你的本地 Maven 仓库。 如果你不知道你要依赖的 jar 包怎么引用,推荐到 mavenrepository.com 网站搜寻。 如果中心仓库没有你需要的 jar 包,需要 把 jar 包安装到本地仓库mvn install:install-file -Dfile=jar包的位置 -DgroupId=上面的groupId -DartifactId=上面的artifactId -Dversion=上面的version -Dpackaging=jar
1.2.4 Spring 专案构建
Spring Tool Suite (STS)eclipse、idea、NetBeans 外挂1.3 Spring 基础配置
Spring 本身的四大原则:使用 POJO 进行轻量级和最小侵入式开发通过依赖注入和基于界面程式设计实现松耦合通过 AOP 和预设习惯进行宣告式程式设计使用 AOP 和模板(Template)较少模式化程式码
1.3.1 依赖注入 (依赖spring-boot-starter-web)
我们常说的控制翻转(Invention Of Control - IoC)和 依赖注入(Dependency injection - DI)在 Spring 环境下其实是等价的。空中翻转是通过依赖注入实现的。依赖注入其实就是容器负责建立物件和维护物件间的依赖关系。
依赖注入目的是为了解耦,提现一种"组合"的概念。
无论 xml 配置、注解配置,还是 Java 配置,都叫配置元资料,元资料就是描述资料的资料。
Spring 容器解析这些配置元资料进行 Bean 初始化、配置和管理依赖。
宣告 Bean 的注解:
@Component 么有明确的角色@Service 业务逻辑层@Repository 资料访问层@Controller 表现层注入 Bean 的注解: 下面三个可以放在 set 方法 或者属性上,我习惯放在属性上
@Autowired Spring 提供的注解@Inject JSR-330 提供的注解@Resource JSR-250 提供的注解JSR 即 Java Specification Requests,Java 规范说明
@Configuration 声明当前类是一个配置类@ComponentScan 自动扫描包名下所有使用 @Service @Component @Repository @Controller 的类并注册为 Bean。
1.3.2 Java 配置
Spring 4.x 推荐使用 Java 配置,Spring Boot 样推荐使用 Java 配置。Java 配置通过 @Configuration 和 @Bean 来实现。
@Configuration 声明当前类是一个配置类,相当于 Spring 的一个 xml 档案@Bean 注解在方法上,声明当前方法返回值为一个 Bean。执行/**
* Java 配置类
*/
@Configuration // 标注当前是一个配置类
public class JavaConfig {
/**
* 普通 Bean 注入
*/
@Bean
public UserService userService(){
return new UserService();
}
/**
* 直接将 userService 作为引数传递给 payService() 方法
* 在 Spring 容器中,只要容器中存在某个 Bean,就可以在另一个 Bean 宣告的方法的引数中注入
*/
@Bean
public PayService payService(UserService userService){
return new PayService(userService);
}
}
/**
* user
*/
public class UserService {
public String sayHello(){
return "user";
}
}
/**
* pay
*/
public class PayService {
private UserService userService;
public PayService(UserService userService) {
this.userService = userService;
}
public String pay(){
return userService.sayHello() + " pay";
}
}
/**
* main
*/
public class RunApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(JavaConfig.class);
UserService userService = context.getBean(UserService.class);
System.out.println(userService.sayHello());
PayService payService = context.getBean(PayService.class);
System.out.println(payService.pay());
// 输出
// user
// user pay
}
}
1.3.3 AOP (依赖spring-boot-starter-aop)
AOP 面向切面程式设计,相对于 OOP 面向物件程式设计。Spring AOP 的存在目的是:解耦。AOP可以让一组类共享相同的行为。在 OOP 中只能通过继承类和实现界面,
使得程式码的耦合度增强,且类继承只能是单继承,阻碍更多行为应用到一组类上,AOP 弥补 OOP 的不足。
Spring 支援 AspectJ 的注解式切面程式设计。
@Aspect 宣告一个切面@After @Before @Around 定义建言(Advice),可直接拦截规则(切点)作为引数@Pointcut 宣告一个切点,定义拦截规则其中符合条件的每一个被拦截处为连线点(JoinPoint)拦截方式
基于注解基于方法规则
/**
* 拦截规则的注解
*/
@Target( { METHOD, FIELD, ANNOTATION_TYPE })
@Retention(RUNTIME)
public @interface Action {
String name();
}
/**
* 使用注解的被拦截类
*/
@Service
public class AnnotationService {
@Action(name = "注解式拦截的 play 操作")
public void play(){}
}
/**
* 使用方法规则的被拦截类
*/
@Service
public class MethodRuleService {
public void play(){}
}
**
* AOP 配置类
*/
@Configuration // 标注当前是一个配置类
@EnableAspectJAutoProxy // 开启 Spring 对 AspectJ 的支援
@ComponentScan("chapter1.aop")
public class AopConfig {
}
/**
* 切面类
*/
@Aspect // 注解宣告一个切面
@Component // 注解成为 Spring 容器管理的 Bean
@Slf4j
public class LogAspect {
/**
* 注解宣告切点
*/
@Pointcut("@annotation(chapter1.aop.Action)")
public void annotationPointCut(){}
/**
* 注解宣告一个建言,并使用 @PointCut 定义的切点
*/
@After("annotationPointCut()")
public void after(JoinPoint joinPoint){
// 通过反射可获取注解上的属性,执行一些业务操作
final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Action action = method.getAnnotation(Action.class);
log.info("Action name: {}", action.name());
}
/**
* 注解宣告一个建言,直接使用拦截规则作为引数
*/
@Before("execution(* chapter1.aop.MethodRuleService.*(..))") // 所有 chapter1.aop.MethodRuleService 包下的所有方法
public void before(JoinPoint joinPoint){
final MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
log.info("方法名: {}", method.getName());
}
}
/**
* AOP 执行类
*/
public class RunApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
// 2 AOP
AnnotationService annotationService = context.getBean(AnnotationService.class);
annotationService.play();
MethodRuleService methodRuleService = context.getBean(MethodRuleService.class);
methodRuleService.play();
// 输出
// Action name: 注解式拦截的 play 操作
// 方法名: play
}
}