3.4 理解BeanFactory
4.1 核心容器
核心容器由spring-beans、spring-core、spring-context和spring-expression(Spring Expression Language, SpEL)4个模块组成。
spring-beans 和spring-core模块是Spring框架的核心模块,包含了控制反转(Inversion of Control, IoC)和依赖注入(Dependency Injection, DI)。BeanFactory使用控制反转对应用程序的配置和依赖性规范与实际的应用程序代码进行了分离。但BeanFactory实例化后并不会自动实例化Bean,只有当Bean被使用时,BeanFactory才会对该Bean进行实例化与依赖关系的装配。
spring-context模块架构于核心模块之上,扩展了Beanfactory,为它添加了Bean生命周期控制、框架事件体系及资源加载透明化等功能。此外,该模块还提供了许多企业级支持,如邮件访问、远程访问、任务调度等,ApplicationContext是该模块的核心接口,它的超类是BeanFactory。与BeanFactory不同,ApplicationContext实例化后会自动对所有的单实例Bean进行实例化与依赖关系的装配,使之处于待用状态。
spring-context-support 模块是对Spring IoC容器及IoC子容器的扩展支持。
spring-context-indexer模块是spring的类管理组件和Classpath扫描组件。
spring-expression模块是统一表达式语言(EL)的扩展模块,可以查询、管理运行中的对象,同时可以方便地调用对象方法,以及操作数组、集合等。它的语法类似于传统EL,但提供了额外的功能,最出色的要数函数调用和简单字符串的模板函数。EL的特性是基于spring产品的需求而设计的,可以非常方便地同Spring IoC进行交互。
导入IDEA P205
第七章 用300行代码手写提炼 Spring 核心原理
P229
启动war的注意事项:
IDEA 配置tomcat 以及环境变量后
启动 war, 可以修改 artifacts 名称
启动url路径 http://localhost:8080/项目名_war名称/[request map]
手动注入的实现
1. 扫描, 通过指定包路径,将class path 存储起来, 例如: com.***.className
2. 实例化
3. 依赖注入
4. ioc ---- handler mapping
// 类的初始化,获取类信息
Class<?> clazz = Class.forName(className);
// ioc
clazz.newInstance()
// 根据注解类型进行策略处理
clazz.isAnnotationPresent(GPController.class)
clazz.isAnnotationPresent(GPRequestMapping.class)
Method[] methods = clazz.getMethods();
method.isAnnotationPresent(GPRequestMapping.class)
方法map,保证HttpServlet 方法调度
clazz.isAnnotationPresent(GPService.class)
需要保证其 interfaces 实例化保存
Class<?> i : clazz.getInterfaces()
5. get post 处理
class extends HttpServlet,override doget、doPost放
为了对查询方法参数适配,需要遍历参数列表
Method method = (Method) handlerMapping.get(url);
Class<?>[] paramTypes = method.getParameterTypes();
Object[] paramValues = new Object[paramTypes.length];
String className = method.getDeclaringClass().getName();
Object instance = mapping.get(className);
Map<String, String[]> params = req.getParameterMap();
int startIndex = 2;
for (Map.Entry<String, String[]> param : params.entrySet()) {
String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "").replaceAll(",\\s", ",");
//如果找到匹配的对象,则开始填充参数值
int index = startIndex++;
paramValues[index] = convert(paramTypes[index], value);
}
paramValues[0] = req;
paramValues[1] = resp;
在迭代 map 时候,不要进行 增加、删除操作,否则会抛
ConcurrentModificationException
// bug Concurrent Modification Exception
for (String className : mapping.keySet()) {
if (!className.contains(".")) {
continue;
}
Class<?> clazz = Class.forName(className);
if (clazz.isAnnotationPresent(GPController.class)) {
mapping.put(className, clazz.newInstance());
String baseUrl = "";
//
if (clazz.isAnnotationPresent(GPRequestMapping.class)) {
GPRequestMapping requestMapping = clazz.getAnnotation(GPRequestMapping.class);
baseUrl = requestMapping.value();
}
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (!method.isAnnotationPresent(GPRequestMapping.class)) {
continue;
}
GPRequestMapping requestMapping = method.getAnnotation(GPRequestMapping.class);
String url = (baseUrl + "/" + requestMapping.value()).replaceAll("/+", "/");
// use other map
handlerMapping.put(url, method);
// this.safePutMap(url, method); // mapping.put(url, method);
System.out.println("Mapped " + url + "," + method);
}
}
}
源码下载&构建
https://github.com/spring-projects/spring-framework/archive/v5.0.2.RELEASE.zip
Gradle | Thank you for downloading Gradle!
修改点:
build.gradle
// 添加aliyun仓库
buildscript {
repositories {
maven { url "https://maven.aliyun.com/repository/spring-plugin" }
maven { url "https://maven.aliyun.com/nexus/content/repositories/spring-plugin" }
maven { url "https://maven.aliyun.com/repository/spring" }
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/repository/central" }
maven { url "https://maven.aliyun.com/repository/google" }
maven { url "https://repo.spring.io/plugins-release" }
}
// 修改插件 org.jetbrains.dokka 版本 0.9.15 到 0.9.17
// 3rd party plugin repositories can be configured in settings.gradle
plugins {
id "com.gradle.build-scan" version "1.8"
id "io.spring.dependency-management" version "1.0.3.RELEASE" apply false
id "org.jetbrains.kotlin.jvm" version "1.1.61" apply true
id "org.jetbrains.dokka" version "0.9.17"
id "org.asciidoctor.convert" version "1.5.6"
}
// 添加全项目 仓库设置
allprojects {
repositories {
maven { url "https://maven.aliyun.com/repository/spring-plugin" }
maven { url "https://maven.aliyun.com/nexus/content/repositories/spring-plugin" }
maven { url "https://maven.aliyun.com/repository/spring" }
maven { url "https://maven.aliyun.com/repository/public" }
maven { url "https://maven.aliyun.com/repository/central" }
maven { url "https://maven.aliyun.com/repository/google" }
maven { url "https://repo.spring.io/plugins-release" }
}
}
第8章 Spring IoC 运行时序图
public class DispatcherServlet extends FrameworkServlet
public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware
ctrl + shift + alt + U look class graphics
理解BeanFactory
Spring 设计核心 org.springframework.beans
架构核心 org.springframework.core
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
AOP 编程理念
支持 AOP 模块 有3个模块组成,spring-aop、spring-aspects和spring-instrument(JVM 生成代理类)。