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

Spring底层架构核心概念解析

BeanDefinition

BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点.比如:

  • beanClass:表示Bean类型
  • scope:表示Bean作用域,单例/原型等
  • lazyInit:表示Bean是否懒加载
  • initMethodName:表示Bean初始化时要执行的方法
  • destoryMethodName:表示Bean销毁时要执行的方法

再Spring中,我们经常会通过以下几种方式来定义Bean:

  1. <bean/>
  2. @Bean
  3. @Component/@Service/@Controller

这些可以称之为 申明式定义Bean.

还可以 编程式定义Bean,那就是直接通过BeanDefinition

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);// 生成一个BeanDefinition对象AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();// 设置beanClass为User.classbeanDefinition.setBeanClass(User.class);// 注册到ApplicationContext中context.registerBeanDefinition("user",beanDefinition);System.out.println(context.getBean("user"));
}// com.fanqiechaodan.entity.User@2034b64c

还可以通过BeanDefinition设置一个Bean的其他属性

// 设置作用域
beanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
// 设置初始化方法
beanDefinition.setInitMethodName("init");
// 设置懒加载
beanDefinition.setLazyInit(true);

和申明式事务,编程式事务类似,通过<bean/>,@Bean,@Component等申明方式所定义的Bean,最终都会被Spring解析为对应的BeanDefinition对象,并放入Spring容器中.

BeanDefinitionReader

BeanDefinitionReader(BeanDefinition读取器),这些BeanDefinitionReader在使用Spring时用的少,但在Spring源码中用的多,相当于Spring的基础设置

AnnotatedBeanDefinitionReader

可以直接把某个类转换为BeanDefinition,并解析该类上的注解

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);AnnotatedBeanDefinitionReader beanDefinitionReader = new AnnotatedBeanDefinitionReader(context);// 将User.class解析为BeanDefinitionbeanDefinitionReader.register(User.class);System.out.println(context.getBean("user"));
}

注意:它能解析的注解是:@Conditional,@DependsOn,@Description,@Lazy,@Primary,@Role,@Scope

XmlBeanDefinitionReader

可以解析<bean/>标签

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(context);// 返回注册Bean的数量int i = beanDefinitionReader.loadBeanDefinitions("spring.xml");System.out.println(context.getBean("user"));
}

ClassPathBeanDefinitionScanner

ClassPathBeanDefinitionScanner是扫描器,但是它的作用与BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描的类进行解析,比如:扫描到的类如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition.

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);ClassPathBeanDefinitionScanner beanDefinitionScanner = new ClassPathBeanDefinitionScanner(context);beanDefinitionScanner.scan("com.fanqiechaodan");System.out.println(context.getBean("userService"));
}

BeanFactory

BeanFactory表示Bean工厂,所以很明显,BeanFactory会负责创建Bean,并且提供获取Bean的API.

而ApplicationContext是BeanFactory的一种,在Spring源码中,是这么定义的:

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {// ...
}

首先,在Java中,接口时可以 多继承 的,我们发现ApplicationContext继承了ListableBeanFactory和HierarchicalBeanFactory,而ListableBeanFactory和HierarchicalBeanFactory都继承至BeanFactory,等同ApplicationContext继承了BeanFactory,ApplicationContext也是BeanFactory的一种,拥有BeanFactory支持的所有功能,不过ApplicationContext比BeanFactory更加强大,ApplicationContext还继承了其他接口,也就表示ApplicationContext还拥有其他的功能.比如MessageSource(国际化),ApplicationEventPublisher(事件发布)等等.

在Spring源码实现中,当我们new一个ApplicationContext时,其底层会new一个BeanFactory出来,当使用ApplicationContext的某些方法时,比如getBean(),底层调用的是BeanFactory的getBean().

在Spring源码中,BeanFactory接口存在一个非常重要的实现类:DefaultListableBeanFactory.所以我们可以直接来使用 DefaultListableBeanFactory,而不用使用ApplicationContext的某个实现类

public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();beanDefinition.setBeanClass(User.class);beanFactory.registerBeanDefinition("user",beanDefinition);System.out.println(beanFactory.getBean("user"));
}

DefaultListableBeanFactory是非常强大的,支持很多功能,可以通过查看DefaultListableBeanFactory的类继承实现结构来看

在这里插入图片描述

它实现了很多接口,表示它拥有很多功能:

  1. AliasRegistry:支持别名功能,一个名字可以对应多个别名
  2. BeanDefinitionRegistry:可以注册,保存,移出,获取某个BeanDefinition
  3. BeanFactory:Bean工厂,可以根据某个Bean的名字/类型/别名获取某个Bean对象
  4. SingletonBeanRegistry:可以注册,获取某个单例Bean
  5. SimpleAliasRegistry:它是一个类,实现了AliasRegistry接口中所定义的功能,支持别名
  6. ListableBeanFactory:在BeanFactory的基础上,增加了其他功能,可以获取所有BeanDefinition的beanNames,可以根据某个类型获取对应的beanNames,可以根据某个类型获取{类型:对应的Bean}的映射关系
  7. HierarchicalBeanFactory:在BeanFactory的基础上,增加了获取父BeanFactory的功能
  8. DefaultSingletonBeanRegisty:它是一个类,实现了SingletonBeanRegistry接口,拥有了直接注册,获取某个单例Bean的功能
  9. ConfigurableBeanFactory:在HierarchicalBeanFactory和SingletonBeanRegistry的基础上,添加了设置父BeanFactory,类加载器(表示可以指定某个类加载器进行类的加载),设置Spring EL表达式解析器(表示可以解析EL表达式),设置类型转化服务(表示可以进行类型转化),可以添加BeanPostprocessor(表示支持Bean的后置处理器),可以合并BeanDefinition,可以销毁某个Bean等等功能
  10. FactoryBeanRegistrySupport:支持了FactoryBean的功能
  11. AutowireCapableBeanFactory:直接继承了BeanFactory,在BeanFactory的基础上,支持创建Bean的过程中能对Bean进行自动装配
  12. AbstractBeanFactory:继承了FactoryBeanRegistrySupport,实现了ConfigurableBeanFactory,这个BeanFactory的功能已经很全面了,但是不能自动装配和获取beanNames
  13. ConfigurableListableBeanFactory:继承了ListableBeanFactory,AutowireCapableBeanFactory,ConfigurableBeanFactory
  14. AbstractAutowireCapableBeanFactory:继承了AbstractBeanFactory,实现了AutowireCapableBeanFactory拥有了自动装配的功能
  15. DefaultListableBeanFactory:直接或间接的继承/实现以上所有类或接口.所以DefaultListableBeanFactory的功能很强大

ApplicationContext

ApplicationContext是个接口,实际上也是一个BeanFactory,不过比BeanFactory更加强大,比如:

  1. HierarchicalBeanFactory:拥有获取父BeanFactory的功能
  2. ListableBeanFactory:拥有获取beanNames的功能
  3. ResourcePatternResolver:资源加载器,可以一次性获取多个资源(文件资源等等)
  4. EnvironmentCapable:可以获取运行时环境,没有设置运行时环境功能
  5. ApplicationEventPublisher:拥有广播事件的功能,没有添加事件监听的功能
  6. MessageSource:拥有国际化功能

ApplicationContext有两个比较重要的实现类:

  1. AnnotationConfigApplicationContext
  2. ClassPathXmlApplicationContext

AnnotationConfigApplicationContext

在这里插入图片描述

  1. ConfigurableApplicationContext:继承了ApplicationContext接口,增加了事件监听器,添加BeanFactoryPostProcessor,设置Environment,获取ConfigurableListableBeanFactory等功能
  2. AbstractApplicationContext:实现了ConfigurableApplicationContext接口
  3. GenericApplicationContext:继承了AbstractApplicationContext,实现了BeanDefinitionRegistry接口,拥有了所有ApplicationContext的功能,并且可以注册BeanDefinition,这个类内置了一个DefaultListableBeanFactory属性
  4. AnnotationConfigRegistry:可以单独注册某个类为BeanDefinition,可以处理该类上的@Configuration注解@Bean注解,同时可以扫描
  5. AnnotationConfigApplicationContext:继承了GenericApplicationContext,实现了AnnotationConfigRegistry接口,拥有了以上所有的功能

ClassPathXmlApplicationContext

在这里插入图片描述

它也是继承了AbstractApplicationContext,但是相对于AnnotationConfigApplicationContext而言,功能没有AnnotationConfigApplicationContext强大,比如不能注册BeanDefinition

国际化

先定义一个MessageSource

@Bean
public MessageSource messageSource() {ResourceBundleMessageSource res = new ResourceBundleMessageSource();res.setBasename("en_CN");res.setDefaultEncoding("UTF-8");return res;
}

en_CN.properties

test=测试

有了这个Bean,可以在任意想要进行国际化的地方使用MessageSource,同时因为ApplicationContext继承了MessageSource,也拥有国际化的功能

public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);System.out.println(context.getBean("messageSource"));System.out.println(context.getMessage("test", null, new Locale("en_CN")));
}// 测试

资源加载

ApplicationContext还拥有资源加载的功能

public static void main(String[] args) throws IOException {ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);Resource userService = context.getResource("file://C:\\devspace\\fanqiechaodan-spring\\src\\main\\java\\com\\fanqiechaodan\\service\\UserService.java");System.out.println(userService.contentLength());System.out.println(userService.getFilename());System.out.println();Resource baidu = context.getResource("https://www.baidu.com/");System.out.println(baidu.contentLength());System.out.println(baidu.getURL());System.out.println();Resource spring = context.getResource("classpath:spring.xml");System.out.println(spring.contentLength());System.out.println(spring.getURL());System.out.println();Resource[] resources = context.getResources("classpath:com/fanqiechaodan/entity/*.class");for (Resource resource : resources) {System.out.println(resource.contentLength());System.out.println(resource.getURL());}
}//  213
//  UserService.java
//  
//  2443
//  https://www.baidu.com/
//  
//  513
//  file:/C:/devspace/fanqiechaodan-spring/target/classes/spring.xml
//  
//  296
//  file:/C:/devspace/fanqiechaodan-spring/target/classes/com/fanqiechaodan/entity/Address.class
//  672
//  file:/C:/devspace/fanqiechaodan-spring/target/classes/com/fanqiechaodan/entity/User.class

获取运行时环境

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);Map<String, Object> systemEnvironment = context.getEnvironment().getSystemEnvironment();System.out.println(systemEnvironment);System.out.println();Map<String, Object> systemProperties = context.getEnvironment().getSystemProperties();System.out.println(systemProperties);System.out.println();MutablePropertySources propertySources = context.getEnvironment().getPropertySources();System.out.println(propertySources);System.out.println(context.getEnvironment().getProperty("sun.jnu.encoding"));
}

事件发布

先定义一个事件监听器

@Bean
public ApplicationListener applicationListener() {return event -> System.out.println("接收到一个事件");
}

在发布事件

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);context.publishEvent("aaa");
}

类型转化

在Spring源码中,有可能需要把String转成其他类型,所以在Spring源码中提供了一些技术来更方便的做对象的类型转化,关于类型转化Spring有很多应用.

PropertyEditor

这其实是JDK中提供的类型转化工具类

public class String2UserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {@Overridepublic void setAsText(String text) throws IllegalArgumentException {User user = new User();user.setName(text);this.setValue(user);}
}public static void main(String[] args) {String2UserPropertyEditor editor = new String2UserPropertyEditor();editor.setAsText("testName");User user = (User) editor.getValue();System.out.println(user.getName());
}

如何向Spring中注册PropertyEditor:

@Bean
public CustomEditorConfigurer customEditorConfigurer(){CustomEditorConfigurer editorConfigurer = new CustomEditorConfigurer();Map<Class<?>, Class<? extends PropertyEditor>> map = new HashMap<>();// 表示String2UserPropertyEditor可以将String转换为User// 在Spring源码中,如果发现当前对象是String,需要的类型为User// 就会使用String2UserPropertyEditor来做类型转化map.put(User.class, String2UserPropertyEditor.class);editorConfigurer.setCustomEditors(map);return editorConfigurer;
}

假设现在有以下Bean:

@Service
public class UserService {@Value("test")private User user;public void test(){System.out.println(user.getName());}
}

使用@Value可以完成对User的赋值

ConversionService

Spring中提供的类型转化服务,它比PropertyEditor更强大

public class String2UserConverter implements ConditionalGenericConverter {@Overridepublic boolean matches(TypeDescriptor sourceType, TypeDescriptor targetType) {return sourceType.getType().equals(String.class) && targetType.getType().equals(User.class);}@Overridepublic Set<ConvertiblePair> getConvertibleTypes() {return Collections.singleton(new ConvertiblePair(String.class, User.class));}@Overridepublic Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {User user = new User();user.setName((String) source);return user;}
}public static void main(String[] args) {DefaultConversionService conversionService = new DefaultConversionService();conversionService.addConverter(new String2UserConverter());User user = conversionService.convert("testName", User.class);System.out.println(user.getName());
}

如何向Spring中注册ConversionService

@Bean
public ConversionServiceFactoryBean conversionServiceFactoryBean(){ConversionServiceFactoryBean conversionServiceFactoryBean = new ConversionServiceFactoryBean();conversionServiceFactoryBean.setConverters(Collections.singleton(new String2UserConverter()));return conversionServiceFactoryBean;
}

TypeConverter

整合了PropertyEditor和ConversionService的功能,是Spring内部用的

public static void main(String[] args) {SimpleTypeConverter simpleTypeConverter = new SimpleTypeConverter();// 整合PropertyEditor//        simpleTypeConverter.registerCustomEditor(User.class,new String2UserPropertyEditor());// 整合ConversionServiceDefaultConversionService conversionService = new DefaultConversionService();conversionService.addConverter(new String2UserConverter());simpleTypeConverter.setConversionService(conversionService);User test = simpleTypeConverter.convertIfNecessary("test", User.class);System.out.println(test.getName());
}

OrderComparator

OrderComparator是Spring所提供的一种比较器,可以用来根据@Order注解或实现Ordered接口来执行值进行比较,从而可以进行排序

@Data
public class A implements Ordered {@Overridepublic int getOrder() {return 1;}}@Data
public class B implements Ordered {@Overridepublic int getOrder() {return 0;}}public static void main(String[] args) {A a = new A();B b = new B();OrderComparator orderComparator = new OrderComparator();System.out.println(orderComparator.compare(a,b));System.out.println();List list = new ArrayList<>();list.add(a);list.add(b);// 按order值升序排序list.sort(orderComparator);System.out.println(list);
}//  1
//
//  [B(), A()]

另外,Spring中还提供了一个OrderComparator的子类:AnnotationAwreOrderComparator,它支持用@Oder来指定order值

@Data
@Order(1)
public class A {}@Data
@Order(0)
public class B {}public static void main(String[] args) {A a = new A();B b = new B();OrderComparator orderComparator = new OrderComparator();System.out.println(orderComparator.compare(a,b));System.out.println();List list = new ArrayList<>();list.add(a);list.add(b);// 按order值升序排序list.sort(orderComparator);System.out.println(list);
}//  1
//
//  [B(), A()]

BeanPostProcessor

BeanPostProcessor表示Bean后置处理器

@Component
public class BeanPostProcessorDemo implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)){System.out.println("userService初始化前");}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if ("userService".equals(beanName)){System.out.println("userService初始化后");}return bean;}
}

一个BeanPostProcessor可以在任意一个Bean的初始化之前以及初始化之后去额外的做一些用户自定义的逻辑,当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean或某部分Bean)

我们可以通过定义BeanPostProcessor来干涉Spring创建Bean的过程.

BeanFactoryPostProcessor

BeanFactoryPostProcessor表示Bean工厂的后置处理器,其实和BeanPostProcessor类似,BeanPostProcessor是干涉Bean的创建过程,BeanFactoryPostProcessor是干涉BeanFactory的创建过程.

@Component
public class BeanFactoryProcessorDemo implements BeanFactoryPostProcessor {/*** 可以对beanFactory进行加工** @param beanFactory* @throws BeansException*/@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println("加工beanFactory");}
}

FactoryBean

我们可以通过BeanPostProcessor来干涉Bean创建的过程,如果想要一个Bean完全由我们来创建同样是可以的.

@Component
public class FactoryBeanDemo implements FactoryBean {@Overridepublic Object getObject() throws Exception {return new UserService();}@Overridepublic Class<?> getObjectType() {return UserService.class;}
}

通过上面这段代码,我们自己创建了一个UserService.并且它将成为Bean.但是通过这种方式创建的Bean.只会经过 初始化后,其他Spring的生命周期是不会经过的,比如依赖注入.而通过@Bean/@Service等等注解定义的Bean是会经过完整的Bean生命周期的.

ExcludeFilter和IncludeFilter

这两个Filter是Spring扫描过程中用来过滤的.ExcludeFilter表示 排除过滤器,IncludeFilter表示 包含过滤器.

/*** 扫描com.fanqiechaodan这个包下的所有类* 但是排除UserService即使它上面有@Component/@Service也不会注册成Bean*/
@ComponentScan(value = "com.fanqiechaodan",excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class)})
public class AppConfig {}
/*** 扫描com.fanqiechaodan这个包下的所有类* 包含UserService即使它上面没有@Component/@Service也会注册成Bean*/
@ComponentScan(value = "com.fanqiechaodan",includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class)})
public class AppConfig {}

FilterType分为:

  1. ANNOTATION:表示是否包含某个注解
  2. ASSIGNABLE_TYPE:表示是否是某个类
  3. ASPECTJ:表示是否符合某个Aspectj表达式
  4. REGEX:表示是否符合某个正则表达式
  5. CUSTOM:自定义

MetadataReader,ClassMetadata,AnnotationMetadata

在Spring中需要去解析类的信息,比如类名,类中的方法,类上的注解,这些都可以称之为类的元数据,所以Spring对类的元数据做了抽象,并提供了一些工具类.

MetadataReader表示类的元数据读取器,默认实现类为 SimpleMetadataReader

public static void main(String[] args) throws IOException {SimpleMetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();// 构造一个MetadataReaderMetadataReader metadataReader = metadataReaderFactory.getMetadataReader("com.fanqiechaodan.service.UserService");// 得到了一个ClassMetadata,并获取类名ClassMetadata classMetadata = metadataReader.getClassMetadata();System.out.println(classMetadata.getClassName());// 获取一个AnnotationMetadata,并获取类上的注解信息AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();for (String annotationType : annotationTypes) {System.out.println(annotationType);}
}

相关文章:

Spring底层架构核心概念解析

BeanDefinition BeanDefinition表示Bean定义,BeanDefinition中存在很多属性用来描述一个Bean的特点.比如: beanClass:表示Bean类型scope:表示Bean作用域,单例/原型等lazyInit:表示Bean是否懒加载initMethodName:表示Bean初始化时要执行的方法destoryMethodName:表示Bean销毁时…...

C++ 44 之 指针运算符的重载

#include <iostream> #include <string> using namespace std;class Students04{ public:int m_age;Students04(int age){this->m_age age;}void showAge(){cout << "年龄是&#xff1a; " << this->m_age << endl;}~Students0…...

onlyoffice在线预览加载优化

背景&#xff1a; 使用容器部署onlyoffice到linux服务器&#xff0c;使用内网访问速度还可以接受&#xff0c;但是如果放到外网路径访问起来&#xff0c;速度就会很慢&#xff0c;甚至加载失败&#xff1b; 优化方案&#xff1a; 预览的过程排除网络因素&#xff0c;可以发现打…...

依赖自动装配

黑马程序员SSM框架 文章目录 1、依赖自动装配2、依赖自动装配的特征 1、依赖自动装配 IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配自动装配方式 按类型&#xff08;常用&#xff09;按名称按构造方法不启用自动装配 配置中使用bean标签auto…...

mysql和redis的双写一致性问题

一&#xff0c;使用方案 在使用redis作为缓存的场景下&#xff0c;我们一般使用流程如下 二&#xff0c;更新数据场景 我们此时修改个某条数据&#xff0c;如何保证mysql数据库和redis缓存中的数据一致呢&#xff1f; 按照常规思路有四种办法&#xff0c;1.先更新mysql数据&a…...

Qwen2——阿里巴巴最新的多语言模型挑战 Llama 3 等 SOTA

引言 经过几个月的期待&#xff0c; 阿里巴巴 Qwen 团队终于发布了 Qwen2 – 他们强大的语言模型系列的下一代发展。 Qwen2 代表了一次重大飞跃&#xff0c;拥有尖端的进步&#xff0c;有可能将其定位为 Meta 著名的最佳替代品 骆驼3 模型。在本次技术深入探讨中&#xff0c;我…...

等级考试3-2021年3月题

作业&#xff1a; #include <iostream> using namespace std; int chonghe(int,int,int,int); int main(){int a[1000],b[1000];int n,ma0;cin>>n;for(int i0;i<n;i){cin>>a[i]>>b[i];}for(int i0;i<n;i){for(int ji1;j<n;j){mamax(ma,chongh…...

Web前端开发PPT:深入探索与实战应用

Web前端开发PPT&#xff1a;深入探索与实战应用 在数字化时代&#xff0c;Web前端开发已成为构建丰富、交互性强的网页应用的关键环节。本次分享旨在通过PPT的形式&#xff0c;带领大家深入探索Web前端开发的精髓&#xff0c;并分享一些实战应用的经验。接下来&#xff0c;我们…...

liunx常见指令

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 二、安装环境 1.租借服务器 2.下载安装 XShell 3.使用xshll登录服务器 三、Linux基础命令 一、文件和命令 ​编辑1、cd 命令 2、pwd 命令 3、ls 命令 4、cp 命令 …...

vscode设置成中文界面

在Visual Studio Code&#xff08;VSCode&#xff09;中设置中文界面&#xff0c;你可以采用以下几种方法&#xff0c;以下是详细步骤&#xff1a; 方法一&#xff1a;通过设置菜单设置中文 打开VSCode&#xff1a;首先&#xff0c;确保你已经打开了VSCode软件。进入设置&…...

python命名空间详解

Python中的命名空间是编程语言设计的一个核心概念&#xff0c;它负责存储变量名与其对应的值之间的映射关系&#xff0c;确保了程序中变量的唯一性和可访问性。命名空间不仅关乎变量的生命周期和作用范围&#xff0c;也是Python中实现封装、避免命名冲突的重要机制。 1. 命名空…...

【日常记录】【vue】vite-plugin-inspect 插件的使用

文章目录 1、vite-plugin-inspect2、安装3、使用4、链接 1、vite-plugin-inspect vite-plugin-inspect 可以让开发者在浏览器端就可以看到vue文件编译后的代码、vue文件的相互依赖关系 2、安装 npm i -D vite-plugin-inspect// vite.config.ts import Inspect from vite-plugi…...

mini web框架示例

web框架&#xff1a; 使用web框架专门负责处理用户的动态资源请求&#xff0c;这个web框架其实就是一个为web服务器提供服务的应用程序 什么是路由&#xff1f; 路由就是请求的url到处理函数的映射&#xff0c;也就是说提前把请求的URL和处理函数关联好 管理路由可以使用一个…...

基于C#开发web网页管理系统模板流程-主界面统计功能完善

点击返回目录-> 基于C#开发web网页管理系统模板流程-总集篇-CSDN博客 前言 紧接上篇->基于C#开发web网页管理系统模板流程-主界面管理员入库和出库功能完善_c#web程序设计-CSDN博客 统计功能是管理系统很常见的功能&#xff0c;例如仓库管理系统要统计某时间段的出入库以…...

chromedriver114以后版本下载地址汇总chromedriver所有版本下载地址汇总国内源下载

谷歌浏览器版本经常会升级&#xff0c;chromedriver 也得下载匹配的版本 chromedriver 114以前版本下载地址https://registry.npmmirror.com/binary.html?pathchromedriver/ 但是自从115版本及其以后网站就找不到了&#xff0c;因此整理了截止2024年6月16日前所有在windows x6…...

x86计算机的启动初期流程 Linux 启动流程

x86计算机的启动初期流程 CPU&#xff1a; step1&#xff0c;加点开机&#xff0c;cpu自己初始化 step2&#xff0c;cpu 从物理地址 0xFFFFFFF0h 取指令执行&#xff1b;此处存放BIOS代码&#xff0c;这些代码可以是由主板自动从 EEPROM中拷贝至此内存地址处&#xff1b;即下…...

P450Rdb: CYP450数据库--地表最强系列--文献精读24

P450Rdb: A manually curated database of reactions catalyzed by cytochrome P450 enzymes P450Rdb: 一个人工整理的细胞色素P450酶催化反应数据库 http://www.cellknowledge.com.cn/p450rdb/ 还有一篇类似CYP450综述-20年-地表最强系列-文献精读-4 要点&#xff1a; P450…...

ubuntu 22.04下载和安装

ubuntu镜像: https://www.releases.ubuntu.com/22.04/ 然后下载vmwareworkstation16 密钥 ZF3R0-FHED2-M80TY-8QYGC-NPKYF...

Fegin如何传参form-data文件

Form-data传输file参数&#xff0c;这个大家都比较清楚&#xff0c;那么针对于Fegin参数file参数该如何操作呢&#xff01;下面截图来找到对应的参数关系。 一、之前我们在postMan中是这种传参的&#xff0c;那么如果使用Feigin来传输文件File 二、在Fegin中传form-data参数&a…...

解决 Visual C++ 17.5 __cplusplus 始终为 199711L 的问题

目录 软件环境问题描述查阅资料解决问题参考文献 软件环境 Visual Studio 2022, Visual C, Version 17.5.4 问题描述 在应用 https://github.com/ToniLipponen/cpp-sqlite 的过程中&#xff0c;发现源代码文件 sqlite.hpp 中&#xff0c;有一处宏&#xff0c;和本项目的 C L…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...