当前位置: 首页 > news >正文

Spring Framework

1.Spring 5下载

1.进入Spring官网

2.进入Spring Framework

3.进入Spring5的github 按照下面步骤

然后根据地址下载需要的版本

Spring的在线文档;

离线文档:

2.Spring学习的核心内容:

1.Spring核心学习内容IOC,AOP,jdbcTemplate,声明式事务

2.IOC:控制反转,可以管理java对象

3.AOP:切面编程

4.JDBCTemplate:是spring提供一套访问数据库的技术,应用性强,相对好理解

5.声明式事务:基于IOC/AOP实现事务管理,理解需要花时间

6.IOC.AOP是重点同时也是难点

Spring几个重要概念:

1.Spring可以整合其他的框架(Spring是管理框架的框架)

2.Spring有两个核心的概念:IOC和AOP

3.传统的开发模式:

程序------>环境//程序读取环境配置,然后自己创建对象

IOC的开发模式:容器--------->程序//容器创建好对象,程序直接使用

1.Spring根据配置文件xml/注解,创建对象,并放入到容器(ConcurrentHashMap)中,并且可以完成对象之间的依赖。

2.当需要使用某个对象实例的时候,就直接从容器中获取即可。

3.程序员可以更加关注如何使用对象完成相应的业务。

4.DI依赖注入,可以理解成事IOC的另外叫法。

5.Spring最大的价值,通过配置,给程序提供需要使用的web层对象,这个是核心价值所在,也是IOC的具体体现,实现解耦。


3.手写简易SpringFrame框架:

实现一下内容:

1.手写模拟Spring容器启动过程底层实现

2.手写模拟Spring解析配置类底层实现

3.手写模拟Spring扫描Bean过程底层实现

4.手写模拟Bean生命周期创建过程底层实现

5.手写模拟Bean生命周期依赖注入过程底层实现

6.手写模拟Bean生命周期Aware回调过程底层实现

7.手写模拟Bean生命周期初始化过程底层实现

8.手写模拟BeanDefinition生成过程底层实现

9.手写模拟@Component,@ComponentScan

10.手写模拟@Autowired,@PostConstruct

11.手写模拟BeanPostProcessor后置处理底层实现

12.手写模拟Spring AOP过程底层实现

13.手写模拟Pointcut,Advisor,Advice底层实现


代码仓库:https://gitee.com/CHEN--YUQIAO/spring-frame 参考学习


4.Spring源码中核心组件的使用与解析

4.1BeanDefinition

BeanDefinition是非常非常核心的一个概念,一个BeanDefinition表示一个Bean定义,Spring会根据BeanDefinition来创建具体的Bean对象。

BeanDefinition中常用的属性:

  • beanClass,表示Bean的类型
  • scope,表示Bean的作用域,比如单例或多例
  • LazyInit:表示Bean是不是懒加载的
  • initMethodName:表示Bean初始化时要执行的方法
  • destoryMethodName:表示Bean销毁时要执行的方法

当使用@Bean,@Component等方式定义Bean时,Spring底层就会解析这些标签和注解生成对应的BeanDefinition对象。(声明式创建)

也可以通过编程式定义和注册BeanDefinition:

      AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext(DeviceService.class);BeanDefinition definition=new AnnotatedGenericBeanDefinition(DeviceService.class);definition.setScope("prototype");definition.setLazyInit(false);definition.setInitMethodName("a");applicationContext.registerBeanDefinition("deviceService",definition);

5.BeanDefinition扫描过程源码解析

package org.springframework.context.annotation;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.type.filter.TypeFilter;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {@AliasFor("value")String[] basePackages() default {};@AliasFor("value")String[] basePackages() default {};Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;Class<?>[] basePackageClasses() default {};Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN;boolean useDefaultFilters() default true;Filter[] includeFilters() default {};Filter[] excludeFilters() default {};boolean lazyInit() default false;@Retention(RetentionPolicy.RUNTIME)@Target({})@interface Filter {FilterType type() default FilterType.ANNOTATION;@AliasFor("classes")Class<?>[] value() default {};@AliasFor("value")Class<?>[] classes() default {};String[] pattern() default {};}}

/** Copyright 2002-2021 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package org.springframework.context.annotation;import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AbstractTypeHierarchyTraversingFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;/*** Parser for the @{@link ComponentScan} annotation.** @author Chris Beams* @author Juergen Hoeller* @author Sam Brannen* @since 3.1* @see ClassPathBeanDefinitionScanner#scan(String...)* @see ComponentScanBeanDefinitionParser*/
class ComponentScanAnnotationParser {private final Environment environment;private final ResourceLoader resourceLoader;private final BeanNameGenerator beanNameGenerator;private final BeanDefinitionRegistry registry;public ComponentScanAnnotationParser(Environment environment, ResourceLoader resourceLoader,BeanNameGenerator beanNameGenerator, BeanDefinitionRegistry registry) {this.environment = environment;this.resourceLoader = resourceLoader;this.beanNameGenerator = beanNameGenerator;this.registry = registry;}public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :BeanUtils.instantiateClass(generatorClass));ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");if (scopedProxyMode != ScopedProxyMode.DEFAULT) {scanner.setScopedProxyMode(scopedProxyMode);}else {Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));}scanner.setResourcePattern(componentScan.getString("resourcePattern"));for (AnnotationAttributes includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) {List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,this.resourceLoader, this.registry);for (TypeFilter typeFilter : typeFilters) {scanner.addIncludeFilter(typeFilter);}}for (AnnotationAttributes excludeFilterAttributes : componentScan.getAnnotationArray("excludeFilters")) {List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment,this.resourceLoader, this.registry);for (TypeFilter typeFilter : typeFilters) {scanner.addExcludeFilter(typeFilter);}}boolean lazyInit = componentScan.getBoolean("lazyInit");if (lazyInit) {scanner.getBeanDefinitionDefaults().setLazyInit(true);}Set<String> basePackages = new LinkedHashSet<>();String[] basePackagesArray = componentScan.getStringArray("basePackages");for (String pkg : basePackagesArray) {String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);Collections.addAll(basePackages, tokenized);}for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {basePackages.add(ClassUtils.getPackageName(clazz));}if (basePackages.isEmpty()) {basePackages.add(ClassUtils.getPackageName(declaringClass));}scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {@Overrideprotected boolean matchClassName(String className) {return declaringClass.equals(className);}});return scanner.doScan(StringUtils.toStringArray(basePackages));}}
ComponentScanAnnotationParser这个类是CompanentScan注解的解析器,用来构建并给scan扫描对象赋值,做扫描前的准备!!

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {Assert.notEmpty(basePackages, "At least one base package must be specified");Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();for (String basePackage : basePackages) {
//扫描basePackage中的所有类,并注册到BeanDefinitionRegistry中Set<BeanDefinition> candidates = findCandidateComponents(basePackage);for (BeanDefinition candidate : candidates) {
//获取bean的scopeScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);candidate.setScope(scopeMetadata.getScopeName());
//生成beanNameString beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
//给BeanDefinition对象中的属性赋默认值if (candidate instanceof AbstractBeanDefinition) {postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);}
//解析@Lazy,@Primary,@Fallback,@DependsOn,@Role,@Description等注解并赋值给BeanDefinition对应的属性if (candidate instanceof AnnotatedBeanDefinition) {AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}
//检查beanName是否已存在if (checkCandidate(beanName, candidate)) {
//BeanDefinitionHolder的作用实在BeanDefinition的基础上 添加了beanNameBeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
//如果设置了ScopedProxyMode,则会生成一个新的BeanDefinition,类型为ScopedProxyFactoryBeandefinitionHolder =AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);beanDefinitions.add(definitionHolder);
//注册beanDefinitionregisterBeanDefinition(definitionHolder, this.registry);}}}return beanDefinitions;}

接下来进入第一个方法,看看是如何实现扫描,获得候选BeanDefinition的:

	public Set<BeanDefinition> findCandidateComponents(String basePackage) {if (this.componentsIndex != null && indexSupportsIncludeFilters()) {return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);}else {return scanCandidateComponents(basePackage);}}

构建扫描路径 → 查找所有类资源 → 读取类元数据 → 双重过滤(规则匹配 + 类合法性) → 生成 Bean 定义

	private Set<BeanDefinition> scanCandidateComponents(String basePackage) {Set<BeanDefinition> candidates = new LinkedHashSet<>();try {String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + '/' + this.resourcePattern;Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);boolean traceEnabled = logger.isTraceEnabled();boolean debugEnabled = logger.isDebugEnabled();for (Resource resource : resources) {if (traceEnabled) {logger.trace("Scanning " + resource);}try {
//利用ASM技术解析每个.class文件得到类的各种信息(类的元数据信息)MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
//利用exludeFileters和includeFilters判断当前class是否为beanif (isCandidateComponent(metadataReader)) {ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);sbd.setSource(resource);
//不能是接口或抽象类,如果是抽象类,但是有@Lookup注解的方法则通过if (isCandidateComponent(sbd)) {if (debugEnabled) {logger.debug("Identified candidate component class: " + resource);}candidates.add(sbd);}else {if (debugEnabled) {logger.debug("Ignored because not a concrete top-level class: " + resource);}}}else {if (traceEnabled) {logger.trace("Ignored because not matching any filter: " + resource);}}}catch (FileNotFoundException ex) {if (traceEnabled) {logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage());}}catch (Throwable ex) {throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex);}}}catch (IOException ex) {throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);}return candidates;}

进入第一重过滤的方法如下:

	protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {for (TypeFilter tf : this.excludeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return false;}}for (TypeFilter tf : this.includeFilters) {if (tf.match(metadataReader, getMetadataReaderFactory())) {return isConditionMatch(metadataReader);}}return false;}

第二重过滤方法如下:

此时,对 findCandidateComponents()方法的剖析就已经完成!!

接下来继续看扫描中的

checkCandidate()方法 即检查beanName是否已经存在

到这里doscan()方法的逻辑就理清楚了!

接下来,总结一下:扫描的入口------> 容器调用refresh()方法

接着会调用到

ConfigurationClassParser类中的
 doProcessConfigurationClass()方法

调用parse()回到上面分析过得,创建一个scanner对象,然后再调用doscan()实现扫描!!

http://www.dtcms.com/a/393959.html

相关文章:

  • 01 定位器项目笔记——知识复习回顾
  • 《Python实现图像剪辑:从基础裁剪到高级滤镜处理》
  • 【图像处理基石】工业检测中使用的图像处理算法有哪些?
  • Arbess,一款比Jenkins轻量、简洁的开源CICD工具
  • 平替PostMan,推荐一款国产开源免费的接口管理工具 - PostIn
  • 17.8 AI智能革命:ChatPPT多模态交互系统3秒生成零冲突PPT,效率提升85%
  • OceanBase数据库锁冲突排查
  • FPGA流水线除法器/加法器/乘法器_设计详解
  • 使用VBA辅助编辑出具有完美导航功能的Word长文档
  • [已更新]2025华为杯C题数学建模研赛C题研究生数学建模思路代码文章成品:围岩裂隙精准识别与三维模型重构
  • 269-基于Python的58同城租房信息数据可视化系统
  • kafka高可用数据不丢失不重复分区内有序性
  • KRaft 运维从静态到动态 Controller
  • 自动语音识别--Zipformer ASR模型
  • 计算机视觉与深度学习 | 图像去雾算法综述:原理、公式与代码实现
  • MySQL sql语言简介和DDL语句介绍
  • [数据结构] 二叉树
  • 4+10+N,华为坤灵“求解”中小企业智能化
  • ECharts 四川省地图渲染与交互效果实现
  • Zynq开发实践(SDK之自定义IP3 - 软件IP联调)
  • VMware虚拟机中CentOS的network配置好后ping不通问题解决方法
  • 传输层————TCP
  • [已更新]2025华为杯B题数学建模研赛B题研究生数学建模思路代码文章成品:无线通信系统链路速率建模
  • 机器学习相关内容
  • 【win11】自动登录,开机进入桌面
  • 关系型数据库系统概述:MySQL与PostgreSQL
  • python编程练习(Day8)
  • 【Linux命令从入门到精通系列指南】apt 命令详解:Debian/Ubuntu 系统包管理的现代利器
  • xtuoj 7的倍数
  • 【开题答辩全过程】以 java牙科门诊管理系统为例,包含答辩的问题和答案