spring class中target总是加载不上配置文件_Java面试系列spring相关

Spring中的Bean是线程安全的吗?

Spring 中的 bean 默认都是单例的,所有线程都共享一个单例实例Bean,因此是存在资源的竞争,是线程不安全的

但是spring中大部分bean都是在方法内部操作,例如:Controller、Service、Dao等,不会对bean的成员变量做查询以外的操作,这种bean是线程安全的。如果非要在这些bean中定义成员变量并修改它,可以声明@Scope("prototype")保证线程安全。

在spring内部有一些bean会对成员变量操作,例如:RequestContextHolder等,这种bean一般通过ThreadLocal来解决线程安全的问题。

@Component 和 @Bean 的区别是什么?

  • @Component注解作用于;而@Bean作用于方法
  • @Component一般是用过类路径来自动装配到spring中;@Bean一般是在方法中产生一个bean,然后将这个bean交给spring管理。
  • @Bean注解比@Component注解的自定义性更强,很多时候我们需要将第三方类库中的bean装配到spring中时,只能通过@Bean来实现。

SpringMVC 工作原理

  • 客户端发送请求,到达DispatcherServlet
  • DispatcherServlet根据请求信息调用HandlerMapping
  • HandlerMapping解析请求到对应的Handler(Controller)后,开始由HandlerAdapter来处理。
  • HandlerAdapter根据Handler调用真正的处理器来处理请求。
  • 处理器处理完以后,返回一个ModelAndView对象。
  • ViewResolver根据ModelAndView中的View查找实际的View。
  • DispaterServlet将ModelAndView中的Model传给View。
  • 最后把实际的View返回给请求者。

在Spring容器初始化的过程中,所有定义的bean都会被初始化吗?

不是,默认只初始化所有未初始化的非懒加载的单例Bean,scope为其它值的bean会在使用到的时候进行初始化,如prototype。

Spring如何解决循环依赖?

spring注入属性方式有多种,但是只有一种循环依赖被解决:setter依赖注入。其他的注入方式,Spring也没有办法解决,只是抛出BeanCurrentlyInCreationException异常。

spring解决循环依赖的方式是采用三级缓存,未等bean创建完成之前就先将实例曝光出去,方便其他bean引用。

核心代码

//singletonObjects指单例对象的cache (一级缓存)
private final Map singletonObjects = new ConcurrentHashMap(256);//singletonFactories指单例对象工厂的cache(三级缓存)private final Map> singletonFactories = new HashMap>(16);//earlySingletonObjects指提前曝光的单例对象的cache(二级缓存)private final Map earlySingletonObjects = new HashMap(16);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   //从一级缓存获取
   Object singletonObject = this.singletonObjects.get(beanName);
   //isSingletonCurrentlyInCreation():判断当前单例bean是否正在创建中
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
         //从二级缓存获取
         singletonObject = this.earlySingletonObjects.get(beanName);
         //allowEarlyReference:是否允许从singletonFactories中通过getObject拿到对象
         if (singletonObject == null && allowEarlyReference) {
            //从三级缓存获取
            ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
            if (singletonFactory != null) {
               singletonObject = singletonFactory.getObject();
               this.earlySingletonObjects.put(beanName, singletonObject);
               this.singletonFactories.remove(beanName);
            }
         }
      }
   }
   return (singletonObject != NULL_OBJECT ? singletonObject : null);
}

图解

958d0d41779d85c4d6c382435bbfe463.png

A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中

此时进行初始化的第二步,发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走create流程,

B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过ObjectFactory.getObject拿到A对象(此时A还没有初始化完全),

B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中

此时返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中,而此时,由于B拿到了A的对象引用,所以B现在引用的A对象完成了初始化

springboot原理,如何实现的自动装配?

首先看启动类上的@SpringBootApplication注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

再看里面的@EnableAutoConfiguration注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {

然后通过@Import注入AutoConfigurationImportSelector类,这个类通过实现DeferredImportSelector来重写selectImports方法去加载META-INF/spring.factories这个外部文件,这个外部文件里面,默认有很多自动配置的类,这些类的定义信息将会被SpringBoot批量的注入到spring容器中,从而实现了自动装配。

相关的starter和自定义starter都是根据这个实现的。

spring事务以及传播机制

spring事务是封装在数据库事务之上的一种事务处理机制,它有两种管理方式:编程式事务和声明式事务

spring事务的传播机制有七种:REQUIRED、REQUIRES_NEW、NESTED、SUPPORTS、NOT_SUPPORTED、MANDATORY和NEVER

详细介绍参考以前的文章:传送门

springboot打包成jar之后,怎么做到不重新打包修改他的properties配置文件?

Spring程序会按优先级从下面这些路径来加载application.properties配置文件

  • 当前目录下的/config目录
  • 当前目录
  • classpath里的/config目录
  • classpath 跟目录

因此,要外置配置文件就很简单了,在jar所在目录新建config文件夹,然后放入配置文件,或者直接放在jar同级目录

bootstrap.properties 和 application.properties 有何区别 ?

单纯做 Spring Boot 开发,可能不太容易遇到 bootstrap.properties 配置文件,但是在结合 Spring Cloud 时,这个配置就会经常遇到了。

  • bootstrap (. yml 或者 . properties):boostrap 由父 ApplicationContext 加载的,比 applicaton 优先加载,配置在应用程序上下文的引导阶段生效。一般来说我们在 Spring Cloud 配置就会使用这个文件。且 boostrap 里面的属性不能被覆盖;
  • application (. yml 或者 . properties):由ApplicatonContext 加载,用于 spring boot 项目的自动化配置。

Spring Boot 打成的 jar 和普通的 jar 有什么区别 ?

  • Spring Boot 项目最终打包成的 jar 是可执行 jar ,这种 jar 可以直接通过 java -jar xxx.jar 命令来运行。
  • Spring Boot 的 jar 无法被其他项目依赖,主要还是他和普通 jar 的结构不同。普通的 jar 包,解压后直接就是包名,包里就是我们的代码,而 Spring Boot 打包成的可执行 jar 解压后,在 \BOOT-INF\classes 目录下才是我们的代码,因此无法被直接引用。

扫一扫,关注我
08060cc416f2617cfb040c1f9bdf2d89.png

Java面试系列-redis相关

2020-09-29

d0b0b72d28d2828ef9e7259bb9e9529e.png

Java面试系列-线程相关(一)

2020-09-03

f6b933b4a804355ca4c6efa5a5d08962.png

Java到底是引用传递还是值传递

2020-08-07

584e1adee29df06f2c2fa29c0e0d2bfc.png

redis分布式锁

2020-06-05

31d667aec708f65fd9ebc2d2ee668027.png

手摸手教你搭建免费图床

2020-05-28

4232523efb43b4dce34422cc2e181f96.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值