Spring-01篇章
一、Spring 简介
Spring是一个开源的Java平台,它提供了全面的基础设施支持来帮助Java开发者更容易地开发Java应用程序。Spring框架的核心特点是依赖注入(DI)和面向切面编程(AOP),这些使得开发者能够以更简洁和模块化的方式构建应用程序。
Spring的主要特点包括:
-
依赖注入:Spring通过依赖注入(DI)来实现组件之间的解耦,这意味着组件的依赖关系由Spring容器在运行时注入,而不是在代码中硬编码。
-
面向切面编程:Spring支持面向切面编程(AOP),允许开发者将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来。
-
事务管理:Spring提供了声明式事务管理,使得事务管理更加简单和透明。
-
数据访问:Spring提供了对各种数据访问技术的集成,如JDBC、Hibernate、JPA等。
-
Web支持:Spring提供了对多种Web框架的集成,如Spring MVC、Spring WebFlux等。
-
安全性:Spring Security是一个功能强大的安全和认证框架,可以与Spring应用程序集成。
-
测试:Spring提供了对单元测试和集成测试的支持,使得测试Spring应用程序更加容易。
-
模块化:Spring框架是高度模块化的,开发者可以根据需要选择使用特定的模块。
-
集成:Spring提供了与其他企业级技术的集成,如消息传递、任务调度等。
-
社区和文档:Spring拥有一个活跃的社区和丰富的文档资源,为开发者提供了大量的学习材料和支持。
Spring框架广泛应用于企业级Java应用开发,它简化了Java应用的开发,提高了代码的可维护性和可测试性。随着时间的推移,Spring已经发展成一个庞大的生态系统,包括Spring Boot、Spring Cloud等子项目,进一步简化了微服务架构的开发和部署。
二、使用及源码讲解
1.导入依赖包
本次演示使用的jdk版本为11,spring版本为 5.3.39
以下是pom文件示例
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.simple.code.generator</groupId>
<artifactId>spring-simple</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-simple</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.39</version>
</dependency>
</dependencies>
</project>
然后我们创建一个HelloService的接口用于演示,并为接口创建实现类,具体代码如下:
HelloService
package com.simple.code.generator.service;
public interface HelloService {
void sayHello();
}
HelloServiceImpl
package com.simple.code.generator.service.impl;
import com.simple.code.generator.service.HelloService;
public class HelloServiceImpl implements HelloService {
public void sayHello() {
System.out.println("hello world !!!");
}
}
编写一个main函数进行测试执行,并查看输出结果。
package com.simple.code.generator;
import com.simple.code.generator.service.HelloService;
import com.simple.code.generator.service.impl.HelloServiceImpl;
public class Main {
public static void main(String[] args) {
HelloService helloService = new HelloServiceImpl();
helloService.sayHello();
}
}
整体结构目录见截图
执行后接下来我们需要思考的问题是,已经引入了spring依赖包,为什么还要进行new对象的操作来获取方式呢,我们将代码稍加改造,在HelloServiceImpl增加@Service注解
package com.simple.code.generator.service.impl;
import com.simple.code.generator.service.HelloService;
import org.springframework.stereotype.Service;
@Service
public class HelloServiceImpl implements HelloService {
public void sayHello() {
System.out.println("hello world !!!");
}
}
将Main入口调用改成如下,修改后再次执行,发现我们不再需要显示的去进行new对象调用,直接从容器中获取对象即可访问到sayHello的内容。接下来我们将通过这个案例去分析讲解什么是AnnotationConfigApplicationContext,以及HelloService是如何被加载初始化的。
package com.simple.code.generator;
import com.simple.code.generator.service.HelloService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
//com.simple.code.generator 对应需要扫描的包名
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.simple.code.generator");
context.getBean(HelloService.class).sayHello();
}
}
2.HelloService注册到容器过程
我们看到AnnotationConfig ApplicationContext的类图如下,接下来我们将围绕ResourceLoader和BeanFactory讲解Context的初始化过程。
如图展示,我们在创建AnnontationConfigApplicationContext在创建的时候会同时创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner。创建后紧跟着会调用ClassPathBeanDefinitionScanner的scan函数扫描我们创建时传入的包路径进行代码文件扫描,扫描后通过GenericApplicationContext的registerBeanDefinition和 registerAlias将找到的文件注册到context容器中,到这一步我们已经看到并掌握了容器扫描以及注册bean的过程,感兴趣的可以随着流程图看下源码中的细节部分。接下来我们继续分析容器的启动过程。
我们继续查看refresh函数,它会执行父类的refresh函数启动spring context容器,并将第一步扫描到的类信息进行初始化,核心代码如下。到这里我们从class的扫描到装载以及初始化容器的过程简单的带大家查看了一遍。
@Override
public void refresh() throws BeansException, IllegalStateException {
this.startupShutdownLock.lock();
try {
this.startupShutdownThread = Thread.currentThread();
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (RuntimeException | Error ex ) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
contextRefresh.end();
}
}
finally {
this.startupShutdownThread = null;
this.startupShutdownLock.unlock();
}
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了spring的使用,而spring提供了IOC、AOP、DI等功能我将会在后续的文章中一一详细描述。如描述有误还望大家不吝赐教,感谢各位耐心观看!