面试-springboot自动装配

61 阅读2分钟

SpringBoot自动装配的原理

什么是自动装配

在刚开始使用Spring的时候,我们引入一个外部依赖,往往需要通过XML或者注解方式进行配置。

比如引入jpa时,

  1. 编写 persistence.xml 文件,声明持久化单元和实体类信息。
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="persistenceUnit">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.example.User</class>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

2.在 Spring XML 配置文件中配置 LocalEntityManagerFactoryBean 和 JpaTransactionManager。

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="persistenceUnit" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

3.在需要使用 JPA 的 DAO 类中通过 @PersistenceContext 注解注入 EntityManager。

@Repository
public class UserDaoImpl implements UserDao {
 
    @PersistenceContext
    private EntityManager entityManager;
 
    // ...
}

相比而言,手动注册 Bean 的方式显得更加复杂繁琐,需要自己在 XML 中配置 Bean 的定义和依赖关系。以下是手动注册 Bean 的示例代码:

<bean id="userDao" class="com.example.dao.UserDaoImpl">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="userService" class="com.example.service.UserServiceImpl">
    <property name="userDao" ref="userDao" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
    <property name="username" value="root" />
    <property name="password" value="password" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="annotatedClasses">
        <list>
            <value>com.example.User</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

从上面的代码可以看出,手动注册 Bean 需要大量的 XML 配置,并且需要手动处理 Bean 的依赖关系。相比之下,使用 Spring Boot 自动装配机制可以大大简化应用程序的配置和部署工作,并提高开发效率。

使用springboot时,我们只需要在yaml,yml,properties配置文件中配置数据库连接参数就可以直接使用了,其他的配置都按照默认配置。

总结:Spring Boot 自动装配是 Spring Boot 框架提供的一种特殊机制,它在应用启动时自动配置 Spring 应用程序所需的所有组件和依赖项。这种机制通过约定大于配置的方式,省去了繁琐的配置过程,并提高了开发效率。

用人话来说:当引入组件时,我们只需要少量配置或者根本无需配置就可以实现功能,其他的配置就按照约定自动设置好了。

自动装配的原理

  1. 扫描外部引用 jar 包中的META-INF/spring.factories文件
  2. 将其配置文件信息加载到spring容器

以pageHelper为例

image.png

找到com.github.pagehelper.autoconfigure.PageHelperAutoConfiguration类

image.png

这也就是pageHelper的默认配置。

值得注意的是,默认配置中有一行注解

image.png

意思是,当容器里有SqlSessionFactory时才加载此配置。

像这样通过ConditionOnXXX注解来控制配置类加载的配置还有很多。

@ConditionalOnBean:当容器里有指定 Bean 的条件下

@ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下

@ConditionalOnClass:当类路径下有指定类的条件下

@ConditionalOnMissingClass:当类路径下没有指定类的条件下

……

感兴趣的同志可以自行搜寻