Spring相关——IOC、Bean、注解

BeanFactory的作用?

BeanFactory是Spring中核心的顶层接口,是Bean的工厂,主要职责就是生产Bean,实现了简单工厂的设计模式,根据传入一个唯一的标识来获得Bean对象,它有非常多的实现类。
BeanFactory也是容器,因为它管理Bean的生命周期。
在这里插入图片描述

BeanDefinition的作用

主要是用来存储Bean的定义信息,决定Bean的生产方式。
比如类名,对象名,作用域,懒加载。
这里是利用了反射的机制,是拿到了类名之后用class.forname拿到类,然后通过newinstance来创建对象。
在这里插入图片描述

ApplicationContext和BeanFactory的关系?

容器和工厂的关系类似于4S店和汽车店的关系。
Application不生产bean,只是通知BeanFactory来生产bean。ApplicationConext实现了BeanFactory。
但是ApplicationCOntext可以自动地把bean注册进来,加载环境变量,实现事件监听,支持多语言。

SpringIOC容器的加载过程

从new ApplicationContext开始加载。

  1. 概念态
  2. 定义态
  3. 纯净态
  4. 成熟态

实例化一个ApplicationContext的对象;
调用bean工厂后置处理器完成扫描;
循环解析扫描出来的类信息;
实例化一个BeanDefinition对象来存储解析出来的信息;
把实例化好的beanDefinition对象put到beanDefinitionMap当中缓存起来, 以便后面实例化bean;
再次调用其他bean工厂后置处理器;

然后,会检查是否lazy,是否抽象等等,再通过反射进行实例化得到纯净的bean,然后进行属性注入,创建AOP等初始化,在put到单例池。

什么是Bean,JavaBean和SpringBean和对象的区别?

由SpringIOC容器管理的对象就是bean,由IOC容器实例化组装和管理的对象。

配置bean有几种方式?
  1. xml配置文件直接配置
  2. @Component(Controller,Service,Repostory) 前提得配置扫描,是直接通过反射得到的。
  3. JavaConfig:@Bean是标注在方法上面的,必须返回一个对象作为Bean,一般是加载Configuration注解下面的。
  4. @Import
Bean的作用域

单例、非单例(单例会减少垃圾回收并且提升性能,快速获取因为每次都是从IOC的缓存里拿,很快。)
Request:每次发起请求都创建一个Bean
Session:每个对话都创建一个对象
application:一个全局应用共享对象

Spring的Bean是线程安全的吗?如何处理单程并发问题?

并不是,单例Bean在类中声明了成员变量并且有读写操作,这个时候就会出现线程不安全的情况。
但是,只需要把成员变量放在方法中,就是线程安全的了。
解决方法:

  1. 设置为多例
  2. 将成员变量放在ThreadLocal中,也就是让成员变量与本地的线程做关联,这样就是线程安全的了。
  3. 使用同步锁 比如加入synchronized就行了。
实例化Bean有几种方式
  1. 构造器方式(反射机制)
  2. 实例工厂方式(@bean)
  3. FactoryBean
解释不同方式的自动装配,spring 自动装配 bean 有哪些方式?

autowired:

  1. byName 根据bean的名字进行装配,如果bean的名字和属性相同,就会自动相配
  2. ByType:根据参数的数据类型进行自动装配
  3. constructor:利用构造函数进行装配
  4. no:不自动装配,手动通过ref属性或者Autowired手动指定需要自动注入的属性。
Bean的生命周期回调方法

有两个重要的bean 生命周期方法,第一个是init , 它是在容器加载bean时候被调用。第二个方法是 destroy 它是在容器卸载类的时候被调用。

bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。

Bean的生命周期
  1. 实例化:通过反射去推断构造函数进行实例化
  2. 属性赋值:解析自动装配,进行依赖注入(循环依赖)
  3. 初始化:调用Aware回调方法,调用初始化生命周期回调方法(如果实现了它)如果bean出现了aop,那就会创建动态代理。
  4. 销毁:Spring容器关闭的时候进行调用。
如何解决循环依赖?

三级缓存。

一级缓存:存储完整的Bean
二级缓存:避免动态代理重复创建
三级缓存:缓存函数接口,可以通过lambda表达式吧方法传进去,但是不会立刻调用,可能会aop创建。

如何在bean创建完之后进行扩展?

beanFactoryPostProcessor

Spring如何避免在并发下获取不完整的Bean?

设置双重检查锁, 在创建bean的过程中加锁,直到放到一级缓存中。但是不是放到一级缓存中,而是把锁加载到二级缓存中。而另一个线程会在能执行后再次寻找一级缓存中的bean。
之所以不放在一级缓存里,是因为性能——因为锁住一级缓存,其他线程就拿不出来其他的bean,会影响其他线程的性能。

JavaConfig是如何代替Spring.xml方式的?
  1. 以前Xml
    a. Spring容器 ClassPathXmlApplicationContext(“xml”)
    b. Spring.xml
    c. bean的配置:< bean scope lazy>
    d. 扫描包: < component-scan>
    e. 引入外部属性配置文件 < property-placeHodeler resource=“xxx.properties”>
    f. < property name=“password” value=“${mysql.password}”></ property>
    g. 指定其他配置文件:<import resource=“”
  2. javaconfig
    a. Spring容器:AnnotationConfigApplicationContext(javaconfig.class)
    b. 配置类 @Configuration
    c. @Bean @Scope @Lazy
    d. 扫描包: @ComponentScan
    e. 引入外部属性配置文件 @PropertySource(“classpath:db.properties”)
    f. @Value(“${mysql.password}”)
    g. @Import @Import({配置类}) 使用比较灵活
如何在没有找到自动注入的bean/找到多个bean的时候不报错?

@Autowired(required = false) 不报错
@Primary 多个bean

@Autowired 注解有什么作用

@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在(可以设置它required属性为false)。
@Autowired 注解提供了更细粒度的控制,包括在何处以及如何完成自动装配。

atuowired和resource有什么区别?

autowired是spring提供的,默认类型。
resource是jdk提供的,默认名字。

使用@Autowired注解自动装配的过程是怎样的?

@Autowired 通过Bean的后置处理器进行解析的
在创建一个spring容器的时候,在构造函数中进行注册。

  1. 在实例化后预解析(解析@Autowired标注的属性、方法 比如:把属性的类型、名称、属性所在的类… 元数据缓存起)
  2. 在属性注入真正的解析(拿到上一步缓存的元数据 去ioc容器帮进行查找,并且返回注入)
  3. 首先根据预解析的元数据拿到 类型去容器中进行查找

如果查询结果刚好为一个,就将该bean装配给@Autowired指定的数据;
如果查询的结果不止一个,那么@Autowired会根据名称来查找;
如果上述查找的结果为空,那么会抛出异常。解决方法时,使用required=false。

Configuration的作用及解析与案例
  1. 用来代替xml配置文件的,可以用@bean来注解bean
  2. 没有configuration也可以配置bean,但是加了可以为配置类创建一个cglib动态代理,保证配置类中@bean方法调用Bean的单例,比如bean可能调用了两次beanB,但是动态代理是去容器中去找,而不是直接去创建bean。

原理:
3. 创建Spring上下文的时候会注册一个解析配置的处理器ConfigurationClassPostProcessor(实现BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor)
4. 在调用invokeBeanFactoryPostProcessor,就会去调用
ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry进行解析配置 (解析配置类说白就是去解析各种注解(@Bean @Configuration@Import @Component … 就是注册BeanDefinition)
5. ConfigurationClassPostProcessor.postProcessBeanFactory去创建cglib动态代理

将一个第三方的类配置为Bean有哪些方式?

  1. @Bean可以
  2. 通过@Import(你想加载的类.class),但是不能干预实例化过程(比如数据库链接)
  3. 通过Spring的扩展接口:BeanDefinitionRegistryPostProcessor
为什么@ComponentScan 不设置basePackage也会扫描?

因为Spring在解析@ComponentScan的时候 拿到basePackage  如果没有设置会将你的类所在的包的地址作为扫描包的地址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值