AcWing
  • 首页
  • 活动
  • 题库
  • 竞赛
  • 校园
  • 应用
  • 文章
    • 题解
    • 分享
    • 问答
  • 吐槽
  • 登录/注册

面试深入之Spring(SpringBoot)

作者: 作者的头像   大菜狗 ,  2022-06-22 17:48:00 ,  所有人可见 ,  阅读 31


3


1

面试深入之Spring(SpringBoot)

Bean的生命周期

bean的创建

整体流程

spring会扫描指定路径的的包,看包下面的每一个类,如果类上面有相关注解,spring就会帮你创建这个类的bean对象,经过依赖注入,初始化前,初始化,AOP,一系列流程创建对象,并管理bean的生命周期

流程总结:

  1. 扫描包(指定包路径)
  2. 推断构造方法
  3. 用构造方法实例化对象(单例bean,即所有getbean的哈希值相同)
  4. 依赖注入
  5. 初始化前
  6. 执行初始化方法
  7. 初始化后(AOP)
  8. 生成代理对象
  9. 得到bean

构造方法的选取

bean要帮你创建对象,依据就是类的构造方法,spring默认用无参构造方法,当只有一个有参构造方法,就用这个,如果有多个有参构造方法,就会报错,这时要手动指定某个构造方法为默认构造方法,就是在方法前加上 @AutoWrite.

构造方法中参数的注入

入果参数传入的是对象,应该怎么注入?从spring对象池里找。

spring对象池可以理解为1个map,对象池里放这所有注册过的bean。找的时候先通过反射根据类型找,如果有多个 ,则根据参数名字去找

上面这个方法叫推断构造方法

AOP和代理对象

手写spring容器的思路

首先要实现一个根据类名,获取对象的getbean方法

如何获取到这些类

想想spring的实现方法,是通过在类上写一些注解。Spring在扫描包的时候,通过这些注解,识别这些类,并

AOP

Sping Bean

Bean的创建

@SpringBootTest
class JavaallApplicationTests {
    @Autowired
    ApplicationContext applicationContext;

    @Test
    void isBeanSingleton() {
        System.out.println(applicationContext.getBean("BeanTest"));
        BeanTest beanTest1 = (BeanTest) applicationContext.getBean("BeanTest");
        BeanTest beanTest2 = (BeanTest) applicationContext.getBean("BeanTest");


        BeanTest beanTest3 = new BeanTest();

        System.out.println("两个通过spring创建的bean:"+(beanTest1 == beanTest2));
        System.out.println("两个通过spring创建的bean的成员对象:"+(beanTest1.getBeanContent() == beanTest2.getBeanContent()));
        System.out.println("通过spring创建的bean和手动创建的对象:"+(beanTest1 == beanTest3));
        System.out.println("通过spring创建的bean和手动创建的对象的成员对象:"+(beanTest1.getBeanContent() == beanTest3.getBeanContent()));


    }
    @Test
    void testClone() throws IOException, ClassNotFoundException {
        BeanTest beanTest1 = new BeanTest();
        BeanTest beanTest2 = beanTest1.clone();
        BeanTest beanTest3 = (BeanTest) beanTest1.deepClone();

        System.out.println("浅拷贝的2个对象:"+(beanTest1 == beanTest2));
        System.out.println("浅拷贝的2个对象的int:"+(beanTest1.getAge()== beanTest2.getAge()));
        System.out.println("浅拷贝的2个对象的string:"+(beanTest1.getName()== beanTest2.getName()));
        System.out.println("浅拷贝的2个对象成员对象:"+(beanTest1.getBeanContent()==beanTest2.getBeanContent()));
        System.out.println("================================================================================");
        System.out.println("浅拷贝的2个对象:"+(beanTest1 == beanTest3));
        System.out.println("浅拷贝的2个对象的int:"+(beanTest1.getAge()== beanTest3.getAge()));
        System.out.println("浅拷贝的2个对象的string:"+(beanTest1.getName()== beanTest3.getName()));
        System.out.println("浅拷贝的2个对象成员对象:"+(beanTest1.getBeanContent()==beanTest3.getBeanContent()));
    }

}

结果:

两个通过spring创建的bean:true
两个通过spring创建的bean的成员对象:true
通过spring创建的bean和手动创建的对象:false
通过spring创建的bean和手动创建的对象的成员对象:false

Bean的注册

beanDefinitionMap

SpringBoot中@Component是如何生效的

SpringBoot帮助Spring解决了哪些问题

1.统一的依赖版本管理

在pom.xml里点开

<artifactId>spring-boot-starter-parent</artifactId>

再点开里面的

<artifactId>spring-boot-dependencies</artifactId>

就可以看到

其对开发场景中常用框架的依赖文件做了统一版本号管理,所以被管理的这些依赖在pom.xml中引入是不需要写版本号

形如:

<artifactId>spring-boot-starter-xxx</artifactId>

就是官方提供的依赖启动器

即提供了官方认为的开发者在该场景业务开发中需要的依赖统一配置

2.自动配置

回忆ssm阶段,当我们想使用第三方依赖,如mybatis ,需要在xml中自己进行手动配置,把这个依赖交给spring管理

   <!-- 配置整合mybatis -->
    <!-- 1.关联数据库文件 -->
    <context:property-placeholder location="classpath:database.properties"/>

    <!-- 2.数据库连接池 -->
    <!--数据库连接池
        dbcp 半自动化操作 不能自动连接
        c3p0 自动化操作(自动的加载配置文件 并且设置到对象里面)
    -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 配置连接池属性 -->
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!-- c3p0连接池的私有属性 -->
        <property name="maxPoolSize" value="30"/>
        <property name="minPoolSize" value="10"/>
        <!-- 关闭连接后不自动commit -->
        <property name="autoCommitOnClose" value="false"/>
        <!-- 获取连接超时时间 -->
        <property name="checkoutTimeout" value="10000"/>
        <!-- 当获取连接失败重试次数 -->
        <property name="acquireRetryAttempts" value="2"/>
    </bean>

    <!-- 3.配置SqlSessionFactory对象 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 注入数据库连接池 -->
        <property name="dataSource" ref="dataSource"/>
        <!-- 配置MyBatis全局配置文件:mybatis-config.xml -->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>

    </bean>

可以想像,我们开发一个业务,需要的依赖很多,如果每一个都需要这么配置的话,将会使开发变的异常麻烦

于是对于这些依赖,spring官方将这些配置帮我们搞好了,无须我们再自己手写这些配置

我们只需要对我们自己写的代码进行配置即可

3.由xml配置文件变为注解+ymal

注:springboot中仍然可以用xml配置,只是现在的开发习惯不用而已,并不是不能用

xml中仍然有许多重复的代码,springboot将配置方式再次简化,用注解实现类的注册

2 评论


用户头像
SolitudeAlma   3天前     回复

不水群,偷偷卷被我抓到了吧


用户头像
JimmyHu   9天前     回复

狗哥,这是把自己的屯的几个月的文件都贴上来了吗


你确定删除吗?

© 2018-2022 AcWing 版权所有  |  京ICP备17053197号-1
用户协议  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标
请输入绑定的邮箱地址
请输入注册信息