Spring 最全Bean的加载和获取方式整理

news2024/12/23 0:00:56

目录

  • 一、 前言
  • 二、Bean加载的九种方式
    • 1. XML配置方式
    • 2. XML+注解配置方式
    • 3. 注解方式
    • 4. 使用@Bean方式
    • 5. 使用@Import方式
    • 6. 容器初始化完毕后注入bean
    • 7. 实现ImportSelector接口
    • 8. 实现ImportBeanDefinitionRegistrar接口
    • 9. 实现BeanDefinitionRegistryPostProcessor接口
  • 三、Bean获取的九种方式
    • 1. 通过BeanFactory获取
    • 2. 启动获取ApplicationContext
    • 3. 实现BeanFactoryAware接口
    • 4. 实现ApplicationContextAware接口
    • 5. 通过继承ApplicationObjectSupport
    • 6. 通过继承WebApplicationObjectSupport
    • 7. 通过BeanFactoryPostProcessor
    • 8. 通过WebApplicationContextUtils
    • 9. 通过ContextLoader

一、 前言

Spring Framework是一个强大且广泛使用的Java应用程序框架,它提供了众多功能和工具,其中之一就是Spring容器。Spring容器是Spring应用程序的核心,它负责管理和维护对象(通常称为"Bean")的生命周期。在Spring中,Bean的加载和获取是常见的操作,本文将总结Spring Bean的加载和获取方式,以帮助开发者更好地理解和使用Spring框架。

二、Bean加载的九种方式

1. XML配置方式

在Spring中,最传统的方式是使用XML配置文件定义Bean。通过在XML配置文件中声明Bean的定义,Spring容器会在应用程序启动时加载这些Bean并管理它们的生命周期。以下是一个简单的XML配置示例:

<!--开启注解扫描-->
<context:component-scan base-package="com.fd.spring"/>

<!--注入bean-->
<bean class="com.fd.spring.domain.User" id="user"/>

测试:

public static void main( String[] args )
    {

        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");

        System.out.println(applicationContext.getBean(User.class));

    }

在这里插入图片描述

2. XML+注解配置方式

Bean类添加自动注入注解

@Component // 自动注入注解
public class User {
}

spring.xml配置文件

<!--开启注解扫描-->
<context:component-scan base-package="com.fd.spring"/>

测试结果:
在这里插入图片描述

3. 注解方式

创建配置类

@Configuration
@ComponentScan(basePackages = "com.fd.spring") // 开启注解扫描
public class SpringConfig {
}

测试方法:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);

System.out.println(applicationContext.getBean(User.class));

测试结果:
在这里插入图片描述

4. 使用@Bean方式

使用@Bean加载第三方bean,并将所在类定义为配置类或Bean

@Configuration
public class SpringConfig1 {

    @Bean
    public Book book() {
        return new Book();
    }

}

测试方法:

AnnotationConfigApplicationContext applicationContext1 = new AnnotationConfigApplicationContext(SpringConfig1.class);

for (String name : applicationContext1.getBeanDefinitionNames()) {
    System.out.println(name);
}

在这里插入图片描述
扩展:

根据条件确认是否加载Bean
引入依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
@Configuration
@Import(User.class)
public class SpringConfig1 {

    @Bean
    public Book book() {
        return new Book();
    }

    @Bean
    @ConditionalOnClass(Mouse.class) // 存在Mouse类就加载Cat
    public Cat tom() {
        return new Cat();
    }

    @Bean
    @ConditionalOnMissingClass("com.fd.spring.domain.Mouse") // 不存在Mouse类就加载Dog
    public Dog dog() {
        return new Dog();
    }

    @Bean
    @ConditionalOnBean(User.class) // 容器存在User bean则加载Food
    public Food food() {
        return new Food();
    }

}

测试结果:
在这里插入图片描述

类似注解:
@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean)
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean)
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)

5. 使用@Import方式

使用@Import注解导入要注入的bean对应的字节码,

@Import(User.class)
public class SpringConfig2 {

}

被导入的bean无需使用注解声明为bean,此形式可以有效的降低源代码与Spring技术的耦合度,在spring技术底层及诸多框架的整合中大量使用

public class User {
}

测试:

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(SpringConfig2.class);

for (String name : applicationContext2.getBeanDefinitionNames()) {
    System.out.println(name);
}

测试结果:
在这里插入图片描述

使用@Import注解导入配置类,会把配置类内的bean一起加载

@Import(SpringConfig1.class)
public class SpringConfig2 {

}

测试结果:
在这里插入图片描述

6. 容器初始化完毕后注入bean

使用上下文对象在容器初始化完毕后注入bean

AnnotationConfigApplicationContext applicationContext2 = new AnnotationConfigApplicationContext(SpringConfig2.class);
// 手动注册
applicationContext2.register(Dog.class);

for (String name : applicationContext2.getBeanDefinitionNames()) {
    System.out.println(name);
}

测试结果:
在这里插入图片描述

7. 实现ImportSelector接口

导入实现了ImportSelector接口的类,实现对导入源的编程式处理(动态加载)

public class MySelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 判断导入类元数据是否存在XX注解
        boolean flag = importingClassMetadata.hasAnnotation("com.fd.spring.annotation.MyAnnotation");
        // 如果存在就导入User类,否则导入Book类
        if (flag) {
            return new String[] {"com.fd.spring.domain.User"};
        } else {
            return new String[] {"com.fd.spring.domain.Book"};
        }
    }
}

自定义注解

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
@MyAnnotation
@Import(MySelector.class)
public class SpringConfig3 {

}

测试方法:

AnnotationConfigApplicationContext applicationContext3 = new AnnotationConfigApplicationContext(SpringConfig3.class);

for (String name : applicationContext3.getBeanDefinitionNames()) {
    System.out.println(name);
}

测试结果:
在这里插入图片描述

取消自定义注解

// @MyAnnotation
@Import(MySelector.class)
public class SpringConfig3 {

}

测试结果:
在这里插入图片描述

扩展:

通过ImportSelector接口,我们就可以根据条件判断确认是否加载Bean

public class MySelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        try {
            // 如果存在Mouse类则加载Cat类
            Class<?> clazz = Class.forName("com.fd.spring.domain.Mouse");

            return new String[] {"com.fd.spring.domain.Cat"};

        } catch (ClassNotFoundException e) {
            return new String[]{};
        }
    }
}

8. 实现ImportBeanDefinitionRegistrar接口

导入实现了ImportBeanDefinitionRegistrar接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的裁定,例如对现有bean的覆盖,进而达成不修改源代码的情况下更换实现的效果

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Book.class).getBeanDefinition();

        registry.registerBeanDefinition("book1",beanDefinition);
    }
}

配置类

@Import(MyImportBeanDefinitionRegistrar.class)
public class SpringConfig4 {
    
}

测试方法:

AnnotationConfigApplicationContext applicationContext4 = new AnnotationConfigApplicationContext(SpringConfig4.class);

for (String name : applicationContext4.getBeanDefinitionNames()) {
  	System.out.println(name);
}

测试结果:
在这里插入图片描述

9. 实现BeanDefinitionRegistryPostProcessor接口

导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的最终裁定

public class MyBeanDefinitionRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {

        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();
        beanDefinitionRegistry.registerBeanDefinition("dog", beanDefinition);
    }
}

配置类

@Import(MyBeanDefinitionRegisterPostProcessor.class)
public class SpringConfig5 {

}

测试结果:
在这里插入图片描述

三、Bean获取的九种方式

在Spring中,Bean的实例化、定位、配置应用程序中的对象及建立对象间的依赖关系,都是在IoC容器中进行的。因此,要在Spring中获取Bean,本质上就是从IoC容器当中获取Bean。

在Spring中,BeanFactory是IoC容器的实际代表者,该接口提供了IoC容器最基本功能。同时,Spring还提供了另外一种类型的容器:ApplicationContext容器。

ApplicationContext容器包括BeanFactory容器的所有功能(BeanFactory的子接口),提供了更多面向应用的功能,它提供了国际化支持和框架事件体系,更易于创建实际应用。

一般情况,我们称BeanFactory为IoC容器,称ApplicationContext为应用上下文。但有时为了方便,也将ApplicationContext称为Spring容器。

通常不建议使用BeanFactory,但BeanFactory 仍然可以用于轻量级的应用程序,如移动设备或基于applet的应用程序,其中它的数据量和速度是显著。

1. 通过BeanFactory获取

通过BeanFactory来获取Bean。基于xml配置文件的时代,可以通过如下方式获得BeanFactory,再通过BeanFactory来获得对应的Bean。这种写法估计也只会出现在古老的项目当中。

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring.xml"));

beanFactory.getBean(User.class);

2. 启动获取ApplicationContext

在项目启动时先获取ApplicationContext对象,然后将其存储在一个地方,以便后续用到时进行使用。这里只介绍基于SpringBoot启动实现:

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        // 启动时,保存上下文,并保存为静态
        ConfigurableApplicationContext ac = SpringApplication.run(Application.class, args);
        SpringContextUtil.setApplicationContext(ac);
    }
}

对应的SpringContextUtil类如下:

public class SpringContextUtil {

    private static ApplicationContext ac;

    public static <T>  T getBean(String beanName, Class<T> clazz) {
        T bean = ac.getBean(beanName, clazz);
        return bean;
    }

    public static void setApplicationContext(ApplicationContext applicationContext){
        ac = applicationContext;
    }
}

启动Spring项目时,直接获取到ApplicationContext的引用,然后将其存储到工具类当中。在使用时,则从工具类中获取ApplicationContext容器,进而从中获得Bean对象。

3. 实现BeanFactoryAware接口

在上面的方式中,XmlBeanFactory已经被废弃,但可以通过其他方式来获得BeanFactory,然后再从BeanFactory中获得指定的Bean。获取BeanFactory实例最简单的方式就是实现BeanFactoryAware接口。

@Component
public class BeanFactoryHelper implements BeanFactoryAware {

 private static BeanFactory beanFactory;

 /**
  * 重写 BeanFactoryAware 接口的方法
  * @param beanFactory :参数赋值给本地属性之后即可使用 BeanFactory
  * @throws BeansException BeansException
  */
 @Override
 public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
  BeanFactoryHelper.beanFactory = beanFactory;
 }
 /**
  * 根据名称获取容器中的对象实例
  * @param beanName :注入的实例必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException
  * @return Object
  */
 public static Object getBean(String beanName) {
  return beanFactory.getBean(beanName);
 }
 /**
  * 根据 class 获取容器中的对象实例
  * @param requiredType :被注入的必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException
  * @param <T> Class
  * @return 对象
  */
 public static <T> T getBean(Class<T> requiredType) {
  return beanFactory.getBean(requiredType);
 }
 /**
  * 判断 spring 容器中是否包含指定名称的对象
  * @param beanName bean名称
  * @return 是否存在
  */
 public static boolean containsBean(String beanName) {
  return beanFactory.containsBean(beanName);
 }
 //其它需求皆可参考 BeanFactory 接口和它的实现类
}

在上述工具类中,便是基于BeanFactoryAware的特性,获得了BeanFactory,然后再通过BeanFactory来获得指定的Bean。

4. 实现ApplicationContextAware接口

通过实现ApplicationContextAware接口,在Spring容器启动时将ApplicationContext注入进去,从而获取ApplicationContext对象,这种方法也是常见的获取Bean的一种方式,推荐使用。

@Component
public class SpringContextUtils implements ApplicationContextAware {

	 private static ApplicationContext ac;
	
	 @Override
	 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
	  ac = applicationContext;
	 }
	
	 public static <T> T getBean(Class<T> clazz) {
	  T bean = ac.getBean(clazz);
	  return bean;
	 }

}

5. 通过继承ApplicationObjectSupport

此种方式依旧是先获得ApplicationContext容器,然后从中获取Bean对象,只不过是基于继承ApplicationObjectSupport类实现的。

@Component
public class SpringContextUtils extends ApplicationObjectSupport {

    private ApplicationContext applicationContext;

    public <T> T getBean(Class<T> clazz) {

        if (applicationContext == null) {
            applicationContext = getApplicationContext();
        }

        if (applicationContext == null) {
            return null;
        } else {
            return applicationContext.getBean(clazz);
        }
    }
}

ApplicationObjectSupport类图如下,我们看到它实现了ApplicationContextAware接口,在Spring容器初始化过程中回调方法setApplicationContext来完成ApplicationContext的赋值。
在这里插入图片描述

6. 通过继承WebApplicationObjectSupport

WebApplicationObjectSupport是ApplicationObjectSupport的一个实现类,提供了Web相关的支持。实现原理与ApplicationObjectSupport一样。

@Component
public class SpringContextUtils extends WebApplicationObjectSupport {

	private ApplicationContext applicationContext;

    public <T> T getBean(Class<T> clazz) {

        if (applicationContext == null) {
            applicationContext = getApplicationContext();
        }

        if (applicationContext == null) {
            return null;
        } else {
            return applicationContext.getBean(clazz);
        }
    }
}

类图如下:
在这里插入图片描述

7. 通过BeanFactoryPostProcessor

Spring工具类,方便在非Spring管理环境中获取Bean。

@Component
public final class SpringUtils implements BeanFactoryPostProcessor{
    
    /** Spring应用上下文环境 */
    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException{
        SpringUtilsS.beanFactory = beanFactory;
    }

    /**
     * 获取对象
     *
     * @param name
     * @return Object 一个以所给名字注册的bean的实例
     * @throws BeansException
     *
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) throws BeansException{
        return (T) beanFactory.getBean(name);
    }

    /**
     * 获取类型为requiredType的对象
     *
     * @param clz
     * @return
     * @throws BeansException
     *
     */
    public static <T> T getBean(Class<T> clz) throws BeansException{
        T result = (T) beanFactory.getBean(clz);
        return result;
    }

    /**
     * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
     *
     * @param name
     * @return boolean
     */
    public static boolean containsBean(String name){
        return beanFactory.containsBean(name);
    }

    /**
     * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
     *
     * @param name
     * @return boolean
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException{
        return beanFactory.isSingleton(name);
    }

    /**
     * @param name
     * @return Class 注册对象的类型
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static Class<?> getType(String name) throws NoSuchBeanDefinitionException{
        return beanFactory.getType(name);
    }

    /**
     * 如果给定的bean名字在bean定义中有别名,则返回这些别名
     *
     * @param name
     * @return
     * @throws NoSuchBeanDefinitionException
     *
     */
    public static String[] getAliases(String name) throws NoSuchBeanDefinitionException{
        return beanFactory.getAliases(name);
    }

    /**
     * 获取aop代理对象
     * 
     * @param invoker
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker){
        return (T) AopContext.currentProxy();
    }
}

8. 通过WebApplicationContextUtils

Spring提供了工具类WebApplicationContextUtils,通过该类可获取WebApplicationContext对象。
这个方法很常见于SpringMVC构建的Web项目中,适用于Web项目的B/S结构。下面两个工具方式的区别是,前者在获取失败时抛出异常,后者返回null。

public class SpringContextUtils2  {

    private ApplicationContext applicationContext;

    public static <T> T getBean(ServletContext request, String name, Class<T> clazz){

        WebApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request);
        // 或者
        WebApplicationContext webApplicationContext1 = WebApplicationContextUtils.getWebApplicationContext(request);
        
       //webApplicationContext1.getBean(name, clazz);

        return webApplicationContext.getBean(name, clazz);
    }

}

9. 通过ContextLoader

使用ContextLoader提供的getCurrentWebApplicationContext方法,也是常用的获取WebApplicationContext的一种方法。

具体实现代码如下:

WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
wac.getBean(beanID);

该方法常见于SpringMVC实现的Web项目中。该方式是一种不依赖于Servlet,不需要注入的方式。但是需要注意一点,在服务器启动时和Spring容器初始化时,不能通过该方法获取Spring容器。

总结:

虽然,spring提供了好几种方法(3、4、5、6、7)可以实现在普通的类中继承或实现相应的类或接口来获取spring 的ApplicationContext对象,但是在使用是一定要注意实现了这些类或接口的普通java类一定要在Spring 的配置文件application-context.xml文件中进行配置或注解配置(注入容器)。否则获取的ApplicationContext对象将为null。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Verilog功能模块——读写位宽不同的异步FIFO

前言 前面的博文已经讲了异步FIFO和同步FIFO&#xff0c;但并没有实现FIFO的读写位宽转换功能&#xff0c;此功能是FIFO的主要功能之一&#xff0c;应用十分广泛&#xff0c;因此&#xff0c;在前面两个模块的基础上&#xff0c;本文使用纯Verilog实现了读写位宽不同的FIFO&…

Plex踩坑——plex web无法找到媒体服务器

现象&#xff1a;之前安装过plex server&#xff0c;然后卸载了。再次重装后&#xff0c;plex web无法找到媒体服务器。 原因&#xff1a;卸载plex server时需要手动将plex的注册表删除&#xff1a;HKEY_CURRENT_USER\Software\Plex, Inc. 原文链接Uninstall Plex Media Serve…

又是一年1024,你还在做程序猿嘛

每年的10月24日&#xff0c;对于广大程序员来说&#xff0c;都有着特殊的意义。这一天是程序员节&#xff0c;一个属于这个独特群体的庆祝活动。在这个特别的日子里&#xff0c;我们不禁要问&#xff1a;又是一年1024&#xff0c;你还在做程序猿嘛&#xff1f; 程序员&#xff…

MATLAB——一维连续小波的分解

%% 学习目标&#xff1a;一维连续小波的分解 %% help wavelet 查询小波工具箱中的所有函数 %% wavedemo 查看案例 clear all; close all; load noissin.mat; %% which noissin.mat figure; subplot(211); plot(noissin); %信号的时域图 10…

【xxl-job】你与xxl-job仅差这个示例

文章目录 摘要介绍底层使用技术和实现原理分布式任务调度任务执行器分片任务任务调度中心 示例代码详解创建一个任务处理类补充配置文件启动xxl-job执行器&#xff0c;并在任务调度中心中添加一个定时任务在任务调度中心中添加一个定时任务&#xff0c;并选择刚刚创建的任务处理…

只要路由器有WPS按钮,佳能打印机连接到Wi-Fi网络的方法就很简单

佳能打印机是很好的设备&#xff0c;可以让你从智能手机、电脑或平板电脑打印照片。它们还提供其他功能&#xff0c;如扫描文档和复制图像。 最新的型号还允许你连接到Wi-Fi&#xff0c;因此你不需要使用电线将设备连接到打印机。 Wi-Fi是通过本地网络传输数据的标准方式。它…

rstudio server 服务器卡死了怎么办

#rstudio 卡死了怎么办 cd ~/.local/share/ ls rm -fr rstudio.old mv ~/.rstudio ~/.rstudio.oldcd ~/.config/ rm -fr .rstudio.old mv ~/.config/rstudio/ ~/.config/rstudio.oldps -ef|grep t040413 |grep rsession |awk {print $2}| xargs kill -9

itbuilder软件在线设计数据库模型,AI与数据库擦出的火花

今天要介绍一款强大的软件&#xff0c;它就是itBuilder软件&#xff0c;一款在线设计数据库模型软件&#xff0c;借助人工智能提高效率&#xff0c;可以生成CRUD代码并推送至开发工具中&#xff1b;它涵盖了几乎所有语言&#xff0c;如Java、Python、JavaScript等&#xff0c;并…

基于Python开源爬虫框架Scrapy租房信息爬取与数据展示工具

获取代码&#xff1a; 知识付费时代&#xff0c;低价有偿获取代码&#xff0c;请理解&#xff01; (1) 下载链接: 后发 (2) 添加博主微信获取&#xff08;有偿&#xff09;,备注来源: mryang511688 (3) 快速扫码咨询&#xff1a; 项目描述 技术&#xff1a;Python、Scrapy、Dj…

红海云签约深圳天使母基金,数智引领金融行业人力资源数字化转型

深圳市天使投资引导基金管理有限公司&#xff08;以下简称“深圳天使母基金”&#xff09;是深圳市人民政府投资发起设立的战略性、政策性基金&#xff0c;目前规模100亿元&#xff0c;是国内规模最大的天使投资类政府引导基金&#xff0c;致力于成为全球领先的天使母基金。 近…

youyeetoo R1卡片电脑(rk3588s)

简介&#xff1a; youyeetoo R1 是风火轮科技专为AIOT市场设计的嵌入式主板(SBC)&#xff0c;体积小但功能强大&#xff0c;搭载瑞芯微旗舰级RK3588s 八核64位处理器&#xff0c;8nm 制程&#xff0c;主频高达2.4GHz&#xff0c;集成ARM Mali-G610 MP4 GPU&#xff0c;内置6 To…

【原创】解决Kotlin无法使用@Slf4j注解的问题

前言 主要还是辟谣之前的网上的用法&#xff0c;当然也会给出最终的使用方法。这可是Kotlin&#xff0c;关Slf4j何事&#xff01;&#xff1f; 辟谣内容&#xff1a;创建注解来解决这个问题 例如&#xff1a; Target(AnnotationTarget.CLASS) Retention(AnnotationRetentio…

CSS基础入门02

目录 1.复合选择器 1.1后代选择器 1.2子选择器 1.3并集选择器 1.4伪类选择器 2.字体属性 2.1设置字体 2.2大小 2.3粗细 2.4文字样式 3.文本属性 3.1文本颜色 3.2设置文本颜色 3.3文本对齐 3.4文本装饰 3.5文本缩进 3.6行高 4.背景属性 4.1背景颜色 4.2背景图…

掌握TikTok时代:MCN的自媒体革命

随着数字时代的到来&#xff0c;媒体和内容创作的格局发生了翻天覆地的变化。社交媒体平台如今是塑造品牌形象、建立个人品牌以及传播信息的关键场所。 在这一领域&#xff0c;TikTok的崛起无疑引领了自媒体革命的浪潮。而多频道网络&#xff08;MCN&#xff09;也发挥着越来越…

IntelliJ IDEA 2023.2正式发布,新UI和Profiler转正

你好&#xff0c;我是YourBatman&#xff1a;做爱做之事❣交配交之人。 &#x1f4da;前言 北京时间2023年7月26日&#xff0c;IntelliJ IDEA 2023.2正式发布。老规矩&#xff0c;吃肉之前&#xff0c;可以先把这几碗汤干了&#xff0c;更有助于消化&#xff08;每篇都很顶哦…

ubuntu双系统安装以及启动时卡死解决办法

目录 一.简介 二.安装 如何安装Ubuntu20.04(详细图文教程-CSDN博客 Ubuntu22.04&#xff08;非虚拟机&#xff09;安装教程&#xff08;2023最新最详细&#xff09;-CSDN博客 三.ubuntu双系统启动时卡死解决办法&#xff08;在ubuntu16.04和18.04测试无误&#xff09; 问题…

程序员节“致敬经典”| Springer Nature高影响力图书合集:专业与应用计算、计算机科学、智能技术与机器人学

​ 每年的10月24日是“程序员节”&#xff0c;节日设立的初衷是为感谢程序员为世界变革带来的无尽可能性和创造力。每位程序员像是一个1024&#xff0c;以最低调但核心的功能模块筑起科技世界。 值此之际Springer Nature致敬经典&#xff0c;特别精选专业与应用计算、计算机科学…

CSS 的盒子Day03(2)

在Web 开发中&#xff0c; CSS 盒子模型是指如何在浏览器引擎中对 HTML 元素进行建模和如何从CSS属性导出 HTML 元素的尺寸。 [3]盒模型的指导方针由 Web 标准万维网联盟 (W3C)特别是 CSS 工作组描述。在 20 世纪 90 年代末和 2000 年代初的多数时间里&#xff0c;主流浏览器中…

如何部署和配置IPv6

环境&#xff1a; IPv6 问题描述&#xff1a; 如何部署和配置IPv6 解决方案&#xff1a; 要了解 IPv6&#xff0c;首先需要了解 IPv4&#xff0c;因为 IPv6 是 IPv4 的升级版本。IPv4 是互联网上最常见的 IP 地址协议&#xff0c;它使用 32 位地址&#xff0c;可以表示大约…

[yolo系列:YOLOV7改进-添加CoordConv,SAConv.]

文章目录 概要CoordConvSAConv 概要 CoordConv&#xff08;Coordinate Convolution&#xff09;和SAConv&#xff08;Spatial Attention Convolution&#xff09;是两种用于神经网络中的特殊卷积操作&#xff0c;用于处理图像数据或其他多维数据。以下是它们的简要介绍&#x…