Spring全家桶面试题(一)之Spring Framework(三)

三、Spring Beans

13. 什么是Spring beans?

在 Spring 中,构成应用程序主干并由Spring IOC容器管理的对象称为bean。bean是一个由Spring IoC容器实例
化、组装和管理的对象。

概念简单明了,我们提取处关键的信息:

  1. bean是对象
  2. bean由SpringIOC管理,由Spring IoC容器实例化、组装和管理

14. 配置Bean有哪几种方式?

  1. xml:
  2. 注解:@Component(@Controller 、@Service、@Repostory、@Configuration这些实际上都是继承的@Component) 前提:需要配置扫描包 反射调用构造方法
  3. javaConfig: @Bean 通常搭配@Configuration的配置类使用,可以自己控制实例化过程,属性配置,如下图。
  4. @Import 3种方式
    springboot自动装配的核心注解@Import
    • 参数如果是普通类,将该类实例化交给IOC容器管理。(除开下面两种都是普通类,4.2之前的版本只能加载有@Configuration的配置类,但后面版本没有该注解也可以加载)
    • 参数如果是ImportBeanDefinitionRegistrar的实现类,支持手工注册bean。
    • 参数如果是ImportSelector的实现类,注册selectImports返回的数组(类全路径)则IOC容器批量注册。

在这里插入图片描述

15. 解释Spring支持的几种bean的作用域

Spring框架支持以下五种bean的作用域:

  • singleton : bean在每个Spring ioc 容器中只有一个实例。
  • prototype:一个bean的定义可以有多个实例。
  • request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情
    形下有效。
  • application:全局 Web 应用程序范围的范围标识符。

注意: 缺省的Spring bean 的作用域是Singleton。使用 prototype 作用域需要慎重的思考,因为频繁创建和销毁 bean
会带来很大的性能开销。

指定作用域的方式:

  1. @Scope注解
    在这里插入图片描述
  2. xml方式
    在这里插入图片描述

16. 单例bean的优势

由于不会每次都创建新对象,所以有一下几个性能上的优势:

  1. 减少了新生成实例的消耗新包括两方面,第一,spring会通过反射或者cglib来生成bean实例这都是耗性能的操作,其次给
    对象分配内存也会涉及复杂算法。 提供服务器内存的利用率 ,减少服务器内存消耗
  2. 减少jvm垃圾回收,由于不会给每个请求都新生成bean实例,所以自然回收的对象少了。
  3. 可以快速获取到bean,因为单例的获取bean操作除了第一次生成之外,其余的都是从缓存里获取的所以很快。

17. Spring框架中的单例bean是线程安全的吗?(阿里一面)

不是,Spring框架中的单例bean不是线程安全的。

spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。
实际上大部分时候 spring bean 无状态的(比如 dao 类),所以某种程度上来说 bean 也是安全的,但如果 bean 有状
态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,
把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean()了,所以就可以保证线程安全了。

扩展

  • 有状态就是有数据存储功能(比如成员变量读写)。
  • 无状态就是不会保存数据

18. Spring如何处理线程并发问题?

单例Bean的情况,如果在类中声明成员变量,并且有读写操作(有状态),就是线程不安全。

解决:

  1. 设置为多例
  2. 将成员变量放在ThreadLocal
  3. 同步锁 会影响服务器吞吐量
  4. 只需要把成员变量声明在方法中(无状态), 单例Bean是线程安全的

19. Spring实例化bean方式的几种方式

  • 构造器方式(反射);

通过例如 、@Component的方式,将完整类路径存到BeanDefinition.beanClass中,Spring在创建bean的时候,就会根据beanClass进行反射,通过反射得到对象实例,反射实际上就是调用构造方法而得到的对象实例

  • 静态工厂方式; factory-method
<!--使用静态工厂方法实例化Bean-->
<bean class="cn.tulingxueyuan.beans.Person" id="person" factory-method="createPersonFactory" >

方法必须是静态方法

public static Person createPersonFactory(){
	Child child=new Child();
	child.setName("儿子");
	return child;
}
  • 实例工厂方式(@Bean); factory-bean+factory-method
<!--使用实例工厂方法实例化Bean-->
<bean class="cn.tulingxueyuan.beans.Person" id="person" factory-bean="personFactory" factory-method="createPersonFactory" >

调用实例化对象的工厂方法,创建实例对象。

@Bean就是这种方式,就是把@Bean所在的配置类读取到factoryBeanName中,factoryMethodName就是@Bean修饰的方法名

  • FactoryBean方式

实现FactoryBean接口,实例化重写getObject方法返回的对象。

四种方式比较,只有第一种是Spring容器控制实例生成,其他三种可以由程序员自己控制它的实例化的过程。

20.什么是bean装配?

装配(注入),或bean 装配是指在Spring 容器中把bean组装到一起,前提是容器需要知道bean的依赖关系,如何通过依赖注入来把它们装配到一起。

手动装配

<bean id="userService" class="com.dcy.service.UserService">
     <property name="name" value="你是我的日月星河"></property>
     <property name="userDao" ref="userDao"></property>
</bean>

@Value方式

自动装配

例如@AutoWired,如果是ByName,就去容器中找到bean对应的对象装配进去。

21.解释不同方式的自动装配,spring 自动装配 bean 有哪些方式?

在spring中,对象无需自己查找或创建与其关联的其他对象,由容器负责把需要相互协作的对象引用赋予各个对象,使
autowire来配置自动装载模式。

在Spring框架xml配置中共有5种自动装配:

  • no:默认的方式是不进行自动装配的,通过手工设置ref属性来进行装配bean。@Autowired 来进行手动指定
    需要自动注入的属性
  • byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean 的name 相同,就进行自
    动装配。
  • byType:通过参数的数据类型进行自动装配。若 IOC 容器中有多个与目标 Bean 类型一致的 Bean. 在这种情况下, Spring 将无法判定哪个 Bean 最合适该属性, 所以不能执行自动装配
  • constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。当 Bean 中存在多个构造器时, 此种自动装配方式将会很复杂. 不推荐使用

JavaBean结构:
在这里插入图片描述
自动装配

<!-- 自动装配 
		byType: 根据类型进行自动装配. 但要求 IOC 容器中只有一个类型对应的 bean, 若有多个则无法完成自动装配.
		byName: 若属性名和某一个 bean 的 id 名一致, 即可完成自动装配. 若没有 id 一致的, 则无法完成自动装配
		在使用 XML 配置时, 自动装用的不多. 但在基于 注解 的配置时, 自动装配使用的较多
	-->

<!-- 自动装配carAuto、addressAuto属性 -->
<bean id="personAuto" class="com.shaohe.spring.beans.autowire.PersonAuto"
	 autowire="byName">
</bean>
  • 在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性. 然而, 若只希望装配个别属性时, autowire 属性就不够灵活了.
  • autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之.
  • 一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些

22. 自动装配的限制(需要注意)

  • 一定要声明set方法
  • 覆盖: 你仍可以用 < constructor-arg >和 < property > 配置来定义依赖,这些配置将始终覆盖自动注入。
  • 基本数据类型:不能自动装配简单的属性,如基本数据类型、字符串 (手动注入还是可以注入基本数
    据类型的 <property value=“” @Value)
  • 模糊特性:自动装配不如显式装配精确,如果有可能尽量使用显示装配。

所以更推荐使用手动装配(@Autowired(根据类型、再根据名字) ref=“” 这种方式 更加灵活更加清晰 )

22. 有哪些生命周期回调方法?有哪几种实现方式?

  • 生命周期回调: 初始化、销毁
    初始化Bean()
    1、@PostConstruct注解标注的方法
    2、执行InitializingBean实现类的afterPropertiesSet方法
    3、执行bean的init-method属性指定的初始化方法
    销毁Bean(在容器关闭时)
    4、@PreDestory注解标注的方法
    5、执行DiposibleBean实现类的destory
    6、执行bean的destroy-method属性指定的销毁方法

启动类

public class Run {

    public static  void main(String[] args) {
        AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MainConfig.class);
        //bean对象销毁是在容器关闭的时候
        context.close();
    }
}

配置类

@Configuration
@ComponentScan//扫描该类所在目录及其子目录
public class MainConfig {

    //initMethod只能使用@Bean和<bean>标签的方式
    //如果使用@Component,没有地方指定initMethod
    @Bean(initMethod ="init2",destroyMethod = "destory2")
    public UserService userService(){
        return new UserService();
    }
}
public class UserService implements InitializingBean, DisposableBean {

    @PostConstruct
    public void init(){
        System.out.println("注解初始化");
    }

    @PreDestroy
    public void destory(){
        System.out.println("注解销毁");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("接口销毁");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("接口初始化");
    }

    public void init2(){
        System.out.println("initMethod初始化");
    }


    public void destory2(){
        System.out.println("destroyMethod销毁");
    }
}

执行结果:
在这里插入图片描述

23.Spring 在加载过程中Bean有哪几种形态:

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值