【Spring面试】五、Bean扩展、JavaConfig、@Import

文章目录

Q1、如何在Spring创建完所有的Bean之后做扩展?

问题涉及的源码分析:

点下Download Sources,把源码注释下载进来。new Spring容器时,调用了refresh方法:

refresh方法:(IoC容器的加载,就是在refresh方法里实现的)

new ApplicationContext() --> refresh() --> finishBeanFactorylnitialization (循环所有的BeanDefinition ,通过BeanFactory.getBean()生成所有的Bean), 这个循环结束之后所有的bean也就创建完了。而在循环结束后,还有一段代码,就是扩展的关键:

即这个实例实现了SmartInitializingSingleton接口,这就是实现的扩展点之一。再看refresh源码,finishBeanFactorylnitialization下面还有个finishRefresh方法:

这里发布了一个ContextRefreshedEvent的事件,我们只要创建个监听器,监听这个事件,也可以完成扩展。

答案:

  • 方式一:实现SmartInitializingSingleton接口
  • 方式二:要创建个监听器,监听ContextRefreshedEvent事件

看下效果,以上即Bean加载完成后输出一句测试的话:

Q2、Spring容器启动时,为什么先加载BeanFactoryPostProcess?

答案:

  • 因为BeanDefinition会在IoC容器加载的时候先注册,而BeanFactoryPostProcess是所有BeanDefinition注册完后做扩展用的,所以要先加载
  • 其次,Ioc容器的加载,即创建Bean,这就需要解析配置类(xml的bean标签、@Component...),负责解析的类也实现了BeanFactoryPostProcessor

Q3、Bean的生产顺序是由什么决定的?

BeanDefinition里装着Bean的一些信息,看创建IoC容器的源码中的refresh方法的源码:

答案:

所以Bean的生产顺序是由BeanDefinition的注册顺序决定的,当然依赖关系也会影响Bean的创建顺序。

java 复制代码
那BeanDefinition的注册顺序由什么决定?

主要由注解(或配置)的解析顺序来决定,由源码看到解析顺序为:

  • @Configuration
  • @Component(当然它还有@Order来细分,这里不细分)
  • @Import的一类
  • @Bean
  • 使用BeanDefinitionRegistryPostProcessor注册的

从上下文拿一下BeanDefinitionNames,是个String[],有序,输出下:

按照上面这个注册顺序,以及Spring中后面的Bean覆盖前面的Bean,还可以这么应用:有个用@Component注册的Bean,我想让他失效并替换成另一个,则可以用@Bean再写一个

Q4、Spring有哪几种配置方式

答案:

有三种方式给Spring容器提供配置的元数据:

  • XML配置文件 :从Spring诞生开始用,spring.xml中用<bean>标签
  • 基于注解 :从Spring2.5+开始,spring.xml <component-scan base-package=""/> + @Component
  • 基于JavaConfig:从Spring3.0开始,使用@Configuration代替xml,使用@Bean代替Bean标签

Q5、JavaConfig是如何替代spring.xml的?

答案:

对于XML

  • 创建Spring容器是new ClassPathXmlApplicationContext("a.xml")
  • 有一个spring.xml文件
  • 配置一个Bean是用bean标签,scope、lazy属性
  • 扫描包用<component-scan base-package=""/>
  • 引入外部的属性配置文件用<property-placeHolder resource="/xx.properties">
  • 引入配置文件后,使用其属性给Bean属性赋值为${}
java 复制代码
<property name="password" value="${mysql.password}"></property>
  • 指定其他配置文件用<import resource="">

对于JavaConfig

  • 创建Spring容器是new AnnotationConfigApplicationContext(javaConfig.class)
  • 有一个配置类,被@Configuration注解修饰
  • 配置一个Bean是用@Bean注解,属性也用注解@Scope、@Lazy
  • 扫描包用@ComponentScan
  • 引入外部的属性配置文件用@PropertySource("classpath:db.properties")
  • 使用配置文件中的值为@Value("${}")
  • 指定其他用@Import(配置类)

以上是应用层的区别,最后,从源码和流程上来说:大方向都是创建Spring容器(同一个接口,不同的实现类),然后加载、解析配置,再注册为BeanDefinition后交给Bean工厂生产。

Q6、@Component、@Controller、@Service、@Repository有何区别?

答案:

这四个注解其实是一个注解,@Controller、@Service、@Repository的源注解都是@Component

之所以分为三种,是因为开发一个项目,常使用三层架构,即控制层、业务层、数据返回层,提供这三个注解用于不同层,提高代码的阅读性。

Q7、@Import可以有几种用法?

答案:

四种:

  • 第一种:直接指定类(如果是配置类,就会按照配置类来解析,如果是个普通类,则直接解析成Bean)
java 复制代码
@Import(UserMapper.class)
@Import(JavaConfig.class)   //此时,JavaConfig这个配置类中的Bean也会生效
  • 第二种:导入一个实现了ImportSelector这个接口的类,这种方式可以一次性注册多个,返回一个String[ ],每一个值是完整类路径
java 复制代码
public class MyImportSelector implements ImportSelector{
	
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata){
		//可以以字符串数组的形式注册多个Bean 
		//字符串必须是类的完整类名
		return new String[]{"com.llg.UserMapper","com.llg.Role"};
	}
}
java 复制代码
@Configuration
@Import(MyImportSelector.class)
public class MainConfig{

}

但注意,这个时候的Bean创建不是正常的IoC加载流程,使用@Import,之前的一个postProcessBeanFactory在所有Beanfinition注册完之后修改这个Import的Bean的信息就会报错

  • 第三种:导入一个实现ImportBeanDefinitionRegistrar的接口的类,这种也可以一次导入多个,是通过BeanDefinitionRegistry来动态注册BeanDefinition,因此这种方式是没有上面在所有Beanfinition注册完之后修改这个Import的Bean的信息就会报错的这个情况的。


  • 第四种:这种其实是第二种的衍生,第二种的接口有个子接口,叫延迟导入选择器,也可以一次导入多个Bean,和ImportSelector的区别是DeferredImportSelector的顺序更靠后


相关推荐
意倾城22 分钟前
JVM内存模型
java·jvm
普通的冒险者33 分钟前
几个简单的数组小练习(适合初学)
java·数据结构
keke1033 分钟前
Java【10_1】用户注册登录(面向过程与面向对象)
java·python·intellij-idea
程序员buddha34 分钟前
Spring & Spring Boot 常用注解整理
java·spring boot·spring
C_V_Better1 小时前
Java Spring Boot 控制器中处理用户数据详解
java·开发语言·spring boot·后端·spring
胡子洲1 小时前
Spring Boot 应用中实现基本的 SSE 功能
java·spring boot·后端
t198751281 小时前
基于Qt的OSG三维建模
java·开发语言
SoFlu软件机器人1 小时前
Java 框架配置自动化:告别冗长的 XML 与 YAML 文件
xml·java·自动化
贰拾wan2 小时前
【Java-EE进阶】SpringBoot针对某个IP限流问题
java·spring boot·后端·idea
青云交2 小时前
【金仓数据库征文】-- 金仓数据库:技术实践天花板级深度解析,手把手教你玩转企业级应用
java·性能调优·集群部署·金仓数据库 2025 征文·数据库平替用金仓·金仓数据库·语法兼容