Spring注册Bean的方式

在这里插入图片描述

文章目录

  • 一、xml方式注册Bean
  • 二、@Configuration+@Bean注册Bean
  • 三、@ComponentScan注册Bean
    • 1. 使用XML文件配置包扫描
    • 2. 使用注解配置包扫描
    • 3. ComponentScans源码
    • 4. ComponentScan源码
    • 5. @ComponentScan + value + includeFilters
    • 6. @ComponentScan + value + excludeFilters
    • 7. @ComponentScan + 自定义过滤规则
  • 四、@Scope设置Bean的作用域
  • 五、@Lazy懒加载Bean
  • 六、@Conditional按条件注册Bean
  • 七、@Import注册Bean
    • 1. @Import快速地导入组件,bean的id默认是组件的全类名
    • 2. 自定义实现ImportSelector接口的类:自定义逻辑,导入组件全类名方式注册bean
    • 3. 自定义实现ImportBeanDefinitionRegistrar接口的类:自定义逻辑,手动注册bean
    • 4. 主从配置类中有相同的bean(例如:myBean()),会先注入@Import(OtherConfig.class)中的myBean(),后注入本配置类中的myBean(),后注入的会覆盖先注入的,所以最终注入的是Bean1。
    • 5. 实现DeferredImportSelector接口的类可以被延迟注入
  • 八、实现FactoryBean接口注册Bean

一、xml方式注册Bean

<!-- 注册Bean -->
<bean id="person" class="com.meimeixia.bean.Person">
	<property name="age" value="18"></property>
	<property name="name" value="lwk"></property>
</bean>
public static void main(String[] args) {
	ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
	Person person = (Person) applicationContext.getBean("person");
	System.out.println(person);
}

二、@Configuration+@Bean注册Bean

/**
 * 以前配置文件的方式被替换成了配置类,即配置类==配置文件
 *
 */
// 这个配置类也是一个组件 
@Configuration // 告诉Spring这是一个配置类
public class MainConfig {

	// @Bean注解是给IOC容器中注册一个bean,类型自然就是返回值的类型,id默认是用方法名作为id
	@Bean
	public Person person() {
		return new Person("lwk", 20);
	}
}
public static void main(String[] args) {
	ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
	Person person = applicationContext.getBean(Person.class);
	System.out.println(person);
	// Person这个类型的组件在IOC容器中的名字是什么呢?
	String[] namesForType = applicationContext.getBeanNamesForType(Person.class);
	for (String name : namesForType) {
		System.out.println(name);
	}

三、@ComponentScan注册Bean

1. 使用XML文件配置包扫描

<!-- 包扫描:只要指定的包及其子包中标注了@Controller@Service@Repository@Component这四个注解中的任何一个的组件,它就会被自动扫描,并加入容器中 -->
<!--当使用includeFilters()方法来指定只包含哪些注解标注的类时,需要禁用掉默认的过滤规则。use-default-filters="false"-->
<context:component-scan base-package="com.lwk" use-default-filters="false"></context:component-scan>

2. 使用注解配置包扫描

/**
 * 以前配置文件的方式被替换成了配置类,即配置类==配置文件
 * @author liayun
 *
 */
// 这个配置类也是一个组件 
@ComponentScan(value="com.lwk") // value指定要扫描的包
@Configuration // 告诉Spring这是一个配置类
public class MainConfig {

	// @Bean注解是给IOC容器中注册一个bean,类型自然就是返回值的类型,id默认是用方法名作为id
	@Bean("person")
	public Person person01() {
		return new Person("liayun", 20);
	}
	
}

3. ComponentScans源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface ComponentScans {
  // 在ComponentScans注解类的内部只声明了一个返回ComponentScan[]数组的value()方法
 ComponentScan[] value();
}

4. ComponentScan源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Repeatable(ComponentScans.class) // 这在Java 8中是一个重复注解,可以在一个类上重复使用@ComponentScan这个注解
public @interface ComponentScan {
 @AliasFor("value")
 String[] basePackages() default {};
 
 Filter[] includeFilters() default {};
 Filter[] excludeFilters() default {};
 
 @Retention(RetentionPolicy.RUNTIME)
 @Target({})
 @interface Filter {
    FilterType type() default FilterType.ANNOTATION;
  }
}

FilterType5种类型:
public enum FilterType {
 ANNOTATION,       // 注解
 ASSIGNABLE_TYPE,  // 类
 ASPECTJ,          // 切面
 REGEX,            // 正则表达式
 CUSTOM            // 自定义规则
}

5. @ComponentScan + value + includeFilters

value指定要扫描的包;
当使用includeFilters()方法来指定只包含哪些注解标注的类时,需要禁用掉默认的过滤规则use-default-filters=false;
结果信息中会一同输出Spring内部的组件名称;
@ComponentScan(value="com.lwk", includeFilters={
//    @Filter(type=FilterType.ANNOTATION, classes={Controller.class}),
//    // 按照给定的类型,只包含BookService类(接口)或其子类(实现类或子接口)的组件
//    @Filter(type=FilterType.ASSIGNABLE_TYPE, classes={BookService.class})
    // 自定义过滤规则:MyTypeFilter类返回true或者false来代表匹配还是没匹配
    @Filter(type=FilterType.CUSTOM, classes={MyTypeFilter.class})
}, useDefaultFilters=false) 
@Configuration
public class MainConfig {
    @Bean("person1")
    public Person person() {
        return new Person("liayun", 20);
    }
}
// 使用includeFilters()方法时,打印结果信息中会一同输出Spring内部的组件名称
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
person1

6. @ComponentScan + value + excludeFilters

@ComponentScan(value="com.lwk", excludeFilters={
    // 除了@Controller和@Service标注的组件之外,该包中剩下的组件都会注册
    @Filter(type= FilterType.ANNOTATION, classes={Controller.class, Service.class})
})

7. @ComponentScan + 自定义过滤规则

/**
 * FilterType.CUSTOM:按照自定义规则进行包含或者排除
 * 如果实现自定义规则进行过滤时,自定义规则的类必须是org.springframework.core.type.filter.TypeFilter接口的实现类。
 */
public class MyTypeFilter implements TypeFilter {
    /**
     * 当实现TypeFilter接口时,需要实现该接口中的match()方法,match()方法的返回值为boolean类型。
     * 当返回true时,表示符合规则,会包含在Spring容器中;
     * 当返回false时,表示不符合规则,不会被包含在Spring容器中;
     * 参数:
     * metadataReader:读取到的当前正在扫描的类的信息
     * metadataReaderFactory:可以获取到其他任何类信息的工厂
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        // 获取当前类注解的信息
        AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
        // 获取当前正在扫描类的类信息(类的类型,类实现的接口。。。)
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        // 获取当前类的资源信息(类的路径。。。)
        Resource resource = metadataReader.getResource();
        // 获取当前正在扫描类的类名
        String className = classMetadata.getClassName();
        System.out.println("--->" + className);

        // 自定义规则
        if (className.contains("service")) {
            return true; // 匹配成功,就会被包含在容器中
        }
        return false; // 匹配不成功,所有的bean都会被排除(除了Spring内置的bean的名称之外)
    }
}

四、@Scope设置Bean的作用域

@Scope("prototype") // 通过@Scope注解来指定该bean的作用范围
@Bean("person2")
public Person person() {
    return new Person("lwk", 25);
}
singleton 默认是单例的,IOC容器起动后立即将bean加载到容器中,以后每次获取直接从容器中获取;容器关闭时被销毁。
prototype 延迟创建bean,不会加入到容器中,每次用到都会重新创建bean;销毁时需要手动调用BeanFactory子类中的destroy()销毁方法。
request   在同一请求中创建一个bean;
session   在同一session中创建一个bean;

五、@Lazy懒加载Bean

@Lazy // 懒加载注解是针对单例bean使用的,IOC容器启动时,不创建bean,延迟到第一次使用时再创建bean
@Bean("person2")
public Person person() {
    return new Person("lwk", 25);
}

六、@Conditional按条件注册Bean

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
 Class<? extends Condition>[] value();
}
1.@Conditional可以标注在方法、类上。
2.可以传一个数组,参数是实现了Conditional接口的实现类,可以在实现类中定义一些规则,满足条件的bean才能注册到容器中。
@Configuration
@Conditional({WindowsCondition.class})  // 类中组件统一设置。满足当前条件,这个类中配置的所有bean注册才能生效
public class MainConfig2 {
    /**
	 * @Conditional({Condition}) : 按照一定的条件进行判断,满足条件给容器中注册bean
	 * 
	 * 如果系统是windows,给容器中注册("bill")
	 * 如果是linux系统,给容器中注册("linus")
	 */
	
	@Bean("bill")
	public Person person01(){
		return new Person("Bill Gates",62);
	}
	
	@Conditional(LinuxCondition.class)
	@Bean("linus")
	public Person person02(){
		return new Person("linus", 48);
	}
}
自定义实现Condition接口的条件类
public class LinuxCondition implements Condition {
    /**
     * ConditionContext:判断条件能使用的上下文(环境)
     * AnnotatedTypeMetadata:当前标注了@Conditional注解的注释信息
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 1. 获取IOC容器使用的BeanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        System.out.println("beanFactory:" + beanFactory);
        // 2. 获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        System.out.println("classLoader:" + classLoader);
        // 3. 获取当前环境信息
        Environment environment = context.getEnvironment();
        // 4. 获取到bean定义的注册类
        /**
         * Spring容器中所有的bean都可以通过BeanDefinitionRegistry对象来进行注册,
         * 因此可以通过它来查看Spring容器中注册了哪些bean。
         * BeanDefinitionRegistry接口中声明的各个方法:
         * registerBeanDefinition(注册bean)、removeBeanDefinition(移除bean)、getBeanDefinition(获取bean定义信息)、containsBeanDefinition(是否包含某个bean)。。。
         */
        BeanDefinitionRegistry registry = context.getRegistry();
        System.out.println("registry:" + registry);

        // 在这还可以做更多的判断,比如判断一下Spring容器中是不是包含有某一个bean
        boolean definition = registry.containsBeanDefinition("person");

		// 动态获取环境变量的值:Windows 10
        String property = environment.getProperty("os.name");
        if(property.contains("linux")){
            return true;
        }
        return false;
    }
}

七、@Import注册Bean

@Import注解的用法:
1.@Import({参数:本项目中的类Color.class,或者 其他配置类otherConfig.class}) bean的id默认是组件的全类名,例如:Color.class bean的id是 com.lwk.bean.Color
2.@Import({参数:自定义实现ImportSelector接口的类:MyImportSelector.class}) 导入组件全类名方式注册bean
3.@Import({参数:自定义实现ImportBeanDefinitionRegistrar接口的类:MyImportBeanDefinitionRegistrar.class}) 手动注册bean
MyImportSelectorMyImportBeanDefinitionRegistrar接口自身不会注册到容器中
4.实现DeferredImportSelector接口的类可以被延迟注入(DeferredImportSelectorImportSelector的子接口,也可以被@Import导入)

1. @Import快速地导入组件,bean的id默认是组件的全类名

@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) 
public class ImportConfig {

}

2. 自定义实现ImportSelector接口的类:自定义逻辑,导入组件全类名方式注册bean

public class MyImportSelector implements ImportSelector {
    // AnnotationMetadata:当前标注@Import注解类的所有注解信息,也就是说不仅能获取到@Import注解里面的信息,还能获取到其他注解的信息
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // MyImportSelector类的selectImports()方法里面就不能返回一个null值,否则会报空指针异常
//        return null;
        return new String[]{"com.lwk.bean.Blue", "com.lwk.bean.Yellow"};
    }
}

3. 自定义实现ImportBeanDefinitionRegistrar接口的类:自定义逻辑,手动注册bean

/**
 * Spring官方在动态注册bean时,大部分套路其实是使用ImportBeanDefinitionRegistrar接口。
 * 所有实现了该接口的类都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口。
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    /**
     * AnnotationMetadata:当前标注了@Import注解所在类的所有注解信息
     * BeanDefinitionRegistry:BeanDefinition注册类
     * 把所有需要添加到容器中的bean;调用BeanDefinitionRegistry.registerBeanDefinition手动注册进来
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean definition = registry.containsBeanDefinition("com.lwk.bean.Red");
        if (definition) {
            // 自定义逻辑:可以指定bean的定义信息,包括bean的类型、作用域等等
            // RootBeanDefinition是BeanDefinition接口的一个实现类
            RootBeanDefinition beanDefinition = new RootBeanDefinition(RainBow.class); 
            // 手动注册一个bean,并且自定义beanName为 "rainBow"
            registry.registerBeanDefinition("rainBow", beanDefinition);
        }
    }
}

4. 主从配置类中有相同的bean(例如:myBean()),会先注入@Import(OtherConfig.class)中的myBean(),后注入本配置类中的myBean(),后注入的会覆盖先注入的,所以最终注入的是Bean1。

@Configuration
@Import(OtherConfig.class)
public class MyConfig { // 主配置 - 程序员编写的
    @Bean
    public MyBean myBean() {
        return new Bean1();
    }
}

@Configuration
static class OtherConfig { // 从属配置 - 自动配置
    @Bean
    public MyBean myBean() {
        return new Bean2();
    }
}

5. 实现DeferredImportSelector接口的类可以被延迟注入

MySelector实现了DeferredImportSelector接口,所以MySelector引用的OtherConfig.class类中的myBean()会延迟注入,也就是会先注入主配置类MyConfig中的Bean1(),
后注入OtherConfig中的Bean2()时,会通过@ConditionalOnMissingBean注解判断是否没有注入过myBean(),由于注入过myBean(),所以此时Bean2()不再注入。

@Configuration
@Import(MySelector.class)
public class MyConfig { // 主配置 - 程序员编写的
    @Bean
    public MyBean myBean() {
        return new Bean1();
    }
}
public class MySelector implements DeferredImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{OtherConfig.class.getName()};
    }
}
@Configuration
public class OtherConfig { // 从属配置 - 自动配置
    @Bean
    @ConditionalOnMissingBean
    public MyBean myBean() {
        return new Bean2();
    }
}

八、实现FactoryBean接口注册Bean

1.从容器中获取FactoryBean类型的bean时,默认获取到的是 自定义实现FactoryBean接口的类中,getObject()创建的bean。
  Object bean1 = applicationContext.getBean("colorFactoryBean");
  System.out.println("bean的类型:" + bean1.getClass());
  bean的类型:class com.lwk.bean.Color
2.要获取自定义实现FactoryBean接口的类本身,需要通过 & + bean的id 获取。
  Object bean2 = applicationContext.getBean("&colorFactoryBean");
  System.out.println("bean的类型:" + bean2.getClass());
  bean的类型:class com.lwk.bean.ColorFactoryBean
  
@Configuration
public class ImportConfig {
    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }
}

// 自定义实现FactoryBean接口的类:创建一个bean,并注册到容器中
public class ColorFactoryBean implements FactoryBean<Color> {

    @Override
    public Color getObject() throws Exception {
        System.out.println("ColorFactoryBean...getObject...");
        return new Color();
    }

    @Override
    public Class<?> getObjectType() {
        // bean的类型
        return Color.class; 
    }

	// 是单例?
	// true:这个bean是单实例,在容器中保存一份
	// false:多实例,每次获取都会创建一个新的bean;
    @Override
    public boolean isSingleton() {
        return true;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/2563.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

rabbitMQ介绍及使用方法

目录 一、MQ概述 二、RabbitMQ简介 三、RabbitMQ的五种工作模式 1、简单模式 2、work queues工作队列模式 3、Pub/Sub 订阅模式 4、Routing 路由模式 5、Topics 通配符模式 一、MQ概述 MQ全称Message Queue (消息队列)&#xff0c;是在消息的传输过程中保存消息的容器…

电商项目后端框架SpringBoot、MybatisPlus

后端框架基础 1.代码自动生成工具 mybatis-plus &#xff08;1&#xff09;首先需要添加依赖文件 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.2</version></dependency><de…

【linux】进程信号——信号的产生

进程信号一、信号概念1.1 信号理解二、产生信号2.1 通过键盘产生信号2.2 捕捉信号自定义signal2.3 系统调用接口产生信号2.3.1 向任意进程发送任意信号kill2.3.2 给自己发送任意信号raise2.3.3 给自己发送指定信号abort2.3.4 理解2.4 硬件异常产生信号2.4.1 除0异常2.4.2 野指针…

蓝桥杯刷题冲刺 | 倒计时17天

作者&#xff1a;指针不指南吗 专栏&#xff1a;蓝桥杯倒计时冲刺 &#x1f43e;马上就要蓝桥杯了&#xff0c;最后的这几天尤为重要&#xff0c;不可懈怠哦&#x1f43e; 文章目录1.长草2.分考场1.长草 题目 链接&#xff1a; 长草 - 蓝桥云课 (lanqiao.cn) 题目描述 小明有一…

Feign远程调用

之前在一篇博客中写了利用RestTemplate发起远程调用的代码&#xff0c;但是存在一下问题&#xff1a;代码可读性差&#xff0c;编程体验不统一&#xff1b;如果参数特别多的话&#xff0c;参数复杂URL难以维护。Feign官方地址&#xff1a;https://github.com/OpenFeign/feignFe…

行业观察 | 来了解一下AI加速器

本文参考网上可查询到的资料简要总结AI加速器的概念和应用等信息 1。 未完待续 更新&#xff1a; 2023 / 3 / 22 行业观察 | 来了解一下AI加速器前言加速器处理器处理器是什么&#xff1f;处理器进化史加速器架构指令集 ISA特定领域的指令集 ISA超长指令字&#xff08;VLIW&a…

如何使用子项目管理方案?

在项目进行中经常发生这样的情况&#xff1a;当你开始为一个项目制定时间表时&#xff0c;你会发现任务的数量太多。你需要把它们全部分组到一些摘要任务中。但随后你看到一堆摘要任务&#xff0c;也想把它们再分组。 这样一来&#xff0c;该项目变得很麻烦&#xff0c;甚至项目…

Matlab进阶绘图第10期—带填充纹理的柱状图

带填充纹理的柱状图是通过在原始柱状图的基础上添加不同的纹理得到的&#xff0c;可以很好地解决由于颜色区分不足而导致的对象识别困难问题。 由于Matlab中未提供纹理填充选项&#xff0c;因此需要大家自行设法解决。 本文使用Kesh Ikuma制作的hatchfill2工具&#xff08;Ma…

gin框架使用websocket实现进入容器内部执行命令

文章目录1. 先决条件2. gin框架实现3. 测试用html文件4. 需要完善1. 先决条件 docker开放远程API端口 2. gin框架实现 type GetCommandResultRequire struct {IpAddr string json:"ip_addr" //传入要控制容器的ip地址ContainerUuid string json:"cont…

对堆题的总体思路

浅说一下pwn堆并用一个简单的例子具体说明给刚入坑堆的小朋友说的一些思路说一下堆是什么堆你可以看成一个结构体数组&#xff0c;然后数组里每个元素都会开辟一块内存来存储数据那么这块用来存储数据的内存就是堆。结构体数组在BSS段上&#xff0c;其内容就是堆的地址&#xf…

动态SQL必知必会

动态SQL必知必会1、什么是动态SQL2、为什么使用动态SQL3、动态SQL的标签4、if 标签-单标签判断5、choose标签-多条件分支判断6、set 标签-修改语句7、foreach标签7.1 批量查询7.2 批量删除7.3 批量添加8、模糊分页查询1、什么是动态SQL 动态 SQL 是 MyBatis 的强大特性之一。如…

阿里巴巴2017实习生笔试题(二)——总结

具体题目来自阿里巴巴2017实习生笔试题&#xff0c;本文仅为整理与汇总。 本题应该往C的多态性进行理解&#xff0c;多态中的动态链接在执行时进行&#xff0c;静态链接在编译时进行。其中A、C、D 都是动态链接的优点&#xff0c;B 时静态链接的优点。 减少页面交换可从如下角…

nginx-动静分离-防盗链-location-4

动静分离 为了加快网站的解析速度&#xff0c;可以把动态页面和静态页面有不同的服务器来解析&#xff0c;加快机械速度。降低原来单个服务器的压力。在动静分离的tomcat时候比较明显&#xff0c;因为tomcat解析静态很慢&#xff0c;其实这些原理的话很好理解&#xff0c;简单…

Baumer工业相机堡盟万兆网相机如何使用千兆网网卡环境保持帧率不变(C++)

项目场景 Baumer工业相机堡盟相机是一种高性能、高质量的工业相机&#xff0c;可用于各种应用场景&#xff0c;如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能&#xff0c;可以实时传输高分辨率图像。此外&#xff0c;该相机还具…

IP、MAC和端口

IP&#xff0c;MAC和端口的概念MAC地址也叫物理地址、硬件地址&#xff0c;由网络设备厂家直接烧录在网卡上的&#xff0c;理论上Mac地址是唯一-的。 但因为Mac地址可以通过程序修改&#xff0c;所以也有可能会重复。IP地址是互联网上的每台设备都规定了-一个唯一的地址, 这个地…

网络安全之认识勒索病毒

一、什么是勒索病毒 勒索病毒&#xff0c;是一种新型电脑病毒&#xff0c;伴随数字货币兴起&#xff0c;主要以邮件、程序木马、网页挂马、服务器入侵、捆绑软件等多种形式进行传播&#xff0c;一旦感染将给用户带来无法估量的损失。如果遭受勒索病毒攻击&#xff0c;将会使绝…

如何用C语言实现渣男通讯录

注意&#xff1a;纯属玩笑&#xff0c;博大家一乐&#xff0c;切勿当真&#x1f4d6;首先我们要知道一个渣男通讯录有哪些信息要包含哪些功能1.你的通讯录要装多少个女朋友你得规定吧&#xff1b;2.每个女朋友的姓名&#xff0c;年龄&#xff0c;电话&#xff0c;爱好这些要有吧…

第29次CCFCSP认证经验总结

鄙人有幸参加了由中国计算机学会举办的第29次计算机软件能力认证考试&#xff0c;在此进行一些考试细节和经验的总结。 如果没有仔细了解过的小白去网上搜索CCFCSP&#xff0c;可能出现的是CSP-J/S&#xff0c;但是详细了解会发现&#xff0c;首先CSP-J/S分初试和复试&#xff…

.NET/C#/GC与内存管理(含深度解析)

详情请看参考文章&#xff1a;.NET面试题解析(06)-GC与内存管理 - 不灬赖 - 博客园 (cnblogs.com)一、对象创建及生命周期一个对象的生命周期简单概括就是&#xff1a;创建>使用>释放&#xff0c;在.NET中一个对象的生命周期&#xff1a;new创建对象并分配内存对象初始化…

【Linux】浅谈shell命令以及运行原理

前言&#xff1a;上篇博文把linux下的基本指令讲解完了。本期我们聊聊Linux下【shell】命令及其运行原理。 目录 Shell的基本概念与作用 原理图展示 shell命令执行原理 Shell的基本概念与作用 Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;ker…