Spring/Spring MVC

1.为什么要使用 Spring?
答案:Spring是一个轻量级的开发框架,提供了丰富的特性和模块,帮助开发者简化开发过程,提高代码的可测试性、可维护性和可扩展性,同时支持面向切面编程、依赖注入等。
---------------------------------------------------------------------------------------
Spring 是一个用于构建企业级 Java 应用程序的框架。它提供了许多功能和特性,使得开发人员能够更快地开发高质量的应用程序。以下是使用 Spring 的一些主要原因:
​
松耦合:Spring 使用依赖注入(Dependency Injection)来管理组件之间的依赖关系。这通过降低组件之间的耦合度,使得应用程序更加灵活、可维护和可测试。
​
面向切面编程(AOP):Spring 支持 AOP,可以将横切关注点(如日志记录、事务管理等)从应用程序的核心逻辑中分离出来。这样可以提高代码的重用性,同时也使代码更加清晰。
​
容器管理:Spring 提供了一个容器(Application Context),用于管理应用程序中的对象。容器管理对象的生命周期,负责创建和管理这些对象,使得开发人员可以更专注于业务逻辑的实现。
​
面向接口编程:Spring 鼓励开发人员通过接口来编程,而不是直接依赖于具体的实现类。这样可以使代码更加灵活和可扩展。同时,Spring 提供了便捷的机制来配置和管理接口和实现类之间的映射关系。
​
数据访问支持:Spring 提供了对各种数据访问技术的支持,包括 JDBC、ORM 框架(如 Hibernate)和 NoSQL 数据库。通过使用 Spring 的数据访问模块,开发人员可以更方便地进行数据库操作。
​
总之,使用 Spring 可以提高开发效率、降低代码的复杂性,并且更容易进行单元测试和集成测试。此外,Spring 还提供了广泛的社区支持和丰富的文档资源,使得开发人员可以更好地学习和使用该框架。
2.解释一下什么是 AOP?
答案:AOP(Aspect-Oriented Programming)是一种编程范式,用于将与业务逻辑无关的横切关注点(如日志、事务管理)从主要业务逻辑中分离出来,以便重用和管理。
---------------------------------------------------------------------------------------
AOP(面向切面编程)是一种编程范式,旨在将应用程序的核心业务逻辑与横切关注点(Cross-cutting Concerns)分离开来。横切关注点指的是那些无法归类到特定类或模块中的功能,比如日志记录、安全性、事务管理等。
​
在传统的面向对象编程中,业务逻辑往往散布在多个类和方法中,而横切关注点则会在这些类和方法中重复出现,导致代码的重复性和繁琐性增加。AOP 通过将这些横切关注点从应用程序的核心逻辑中剥离出来,使得开发人员能够更好地关注业务逻辑的实现,同时提高了代码的可重用性和可维护性。
​
AOP 的核心概念是切面(Aspect),切面定义了一组与横切关注点相关的行为。切面通过使用特定的语法(通常是基于注解或 XML 配置)来描述横切关注点,并将这些行为织入到应用程序的目标对象中。织入(Weaving)是指将切面的行为与目标对象的方法进行动态的结合。
​
AOP 的实现方式有多种,其中最常见的是使用代理模式。在代理模式下,AOP 框架通过动态代理生成目标对象的代理对象,并在代理对象的方法中织入切面的行为。这样,当应用程序调用代理对象的方法时,切面的行为就会被触发。
​
AOP 在许多应用场景中非常有用,特别是在横切关注点需要在多个类或模块中共享和重复使用的情况下。通过将这些关注点集中管理,AOP 可以提高代码的可维护性、重用性和可测试性。
3.解释一下什么是 IOC?
答案:IOC(Inversion of Control)是一种设计原则,它将对象的创建和管理交给容器,而不是由程序员手动管理。Spring的IOC容器负责创建、注入和管理对象。
---------------------------------------------------------------------------------------
IOC(Inversion of Control,控制反转)是一种编程设计原则,旨在解耦组件之间的依赖关系,提高代码的灵活性和可测试性。
​
传统的编程模式中,对象的创建和管理通常由调用者来负责。这意味着调用者需要主动创建依赖的对象,并负责将这些对象传递给被调用者。这样的设计会导致高度耦合的代码,使得对象之间的依赖关系变得紧密,难以修改和扩展。
​
而IOC 的概念正是将对象的创建和管理权利反转给了容器或框架。在 IOC 中,应用程序的各个组件(例如类或模块)通过依赖关系描述(通常是通过注解或配置文件)告诉容器需要依赖哪些其他组件。容器在运行时负责创建和管理这些对象,并将它们注入到需要依赖的地方,而不是由调用者主动创建。
​
通过使用 IOC,我们可以实现以下几个好处:
​
解耦:IOC 将对象之间的依赖关系从应用程序代码中抽离出来,减少了耦合度。这使得代码更加灵活,可以更方便地修改、测试和扩展。
​
可替换性:由于组件之间的依赖关系被声明在配置中,因此可以更轻松地替换具体的实现。例如,可以通过修改配置文件来更换不同的实现,而无需修改大量的代码。
​
可测试性:由于组件依赖被外部容器管理,我们可以更容易地进行单元测试,通过在测试环境中注入模拟对象来模拟外部依赖。
​
集中管理:通过IOC容器,我们可以集中管理对象的生命周期和配置,提高了代码的可维护性和可管理性。
​
Spring框架是一个经典的IOC容器实现,它提供了强大的依赖注入功能,可以帮助开发人员更好地应用IOC原则。
4.Spring 有哪些主要模块?
答案:Spring包括核心容器、AOP模块、数据访问/集成模块、Web模块和消息模块等主要模块, 用于支持不同的开发需求。
---------------------------------------------------------------------------------------
Spring 是一个大型的开源框架,由多个模块组成,每个模块的主要目的是提供特定的功能。下面是 Spring 中一些常见的主要模块:
​
Spring Core:Spring 的核心模块,提供了 IoC 容器和依赖注入 (DI) 功能。它可以将不同组件中的依赖关系解耦并创建解决依赖关系的对象。
​
Spring AOP:面向切面编程(AOP)模块,提供了在运行时动态地将横切关注点(如安全性、事务管理、日志记录等)织入到应用程序中的能力。
​
Spring JDBC:提供了对 JDBC 的支持,它允许开发人员使用 Spring 配置和 API 轻松访问数据库。
​
Spring ORM:提供了使用对象关系映射 (ORM) 框架(如 Hibernate 或 JPA)访问数据库的支持。
​
Spring Web:提供了构建 Web 应用程序的支持,包括处理 HTTP 请求和响应、模板引擎、视图解析、文件上传等功能。
​
Spring MVC:基于 Spring Web 提供了一套 MVC(Model-View-Controller)框架,用于构建 Web 应用程序。
​
Spring Test:提供了进行单元测试和集成测试的支持,包括使用 JUnit 的测试框架和 Spring 的模拟对象。
​
此外,Spring 还提供了其他一些模块,例如:
​
Spring Security:提供了身份验证、授权和安全性的支持。
​
Spring Data:提供了访问持久化数据存储的 API,包括访问关系型数据库和 NoSQL 数据库。
​
Spring Integration:提供了通过消息传递和各种传输协议集成系统的支持。
​
Spring Batch:提供了处理大容量批处理作业的功能。
​
这些模块共同提供了一个完整的框架,能够满足开发人员在构建企业级应用程序时所需的大多数功能。
5.Spring 常用的注入方式有哪些?
答案:Spring的常用注入方式有构造器注入、属性注入和方法注入。
---------------------------------------------------------------------------------------
Spring 框架提供了多种方式来实现依赖注入(Dependency Injection,DI)。以下是一些常用的注入方式:
​
构造函数注入(Constructor Injection):通过构造函数将依赖项传递给目标对象。通过构造函数来注入依赖项可使目标对象在创建时就具有必需的依赖关系。
示例:

public class MyClass {
    private MyDependency myDependency;
​
    public MyClass(MyDependency myDependency) {
        this.myDependency = myDependency;
    }
}
Setter 方法注入(Setter Injection):通过 setter 方法将依赖项注入到目标对象中。通过 setter 方法注入依赖项可为目标对象提供更大的灵活性,允许在运行时更改依赖项。
示例:

​
public class MyClass {
    private MyDependency myDependency;
​
    public void setMyDependency(MyDependency myDependency) {
        this.myDependency = myDependency;
    }
}
注解注入(Annotation Injection):使用注解来标记需要注入的字段或方法,Spring 在实例化对象时会自动将对应的依赖项注入。
示例:
​

public class MyClass {
    @Autowired
    private MyDependency myDependency;
}
接口注入(Interface Injection):通过实现特定接口来接收依赖项,Spring 会在运行时注入实现了该接口的对象。
示例:
​

public interface MyDependencyInjector {
    void inject(MyDependency myDependency);
}
​
public class MyClass implements MyDependencyInjector {
    private MyDependency myDependency;
​
    @Override
    public void inject(MyDependency myDependency) {
        this.myDependency = myDependency;
    }
}
可以使用适合应用程序需求的注入方式来实现依赖注入。在实际开发中,通常会结合不同的注入方式来管理和注入依赖项。
6.Spring 中的 bean 是线程安全的吗?
答案:默认情况下,Spring中的单例(Singleton)bean是线程不安全的,多个线程可能共享同一 个实例。如果需要线程安全的bean,可以使用原型(Prototype)作用域。
---------------------------------------------------------------------------------------
在 Spring 框架中,每个 Bean 默认情况下都是单例的,即默认情况下 Spring 容器只会创建一个该类型的 Bean 实例,并在需要时重用它。因此,Bean 不是线程安全的,当多个线程同时访问 Bean 实例时可能会引发线程安全问题。
​
需要注意的是,如果 Bean 进行了适当的配置,它们可以变得线程安全。例如,你可以在 Bean 声明中添加 @Scope("prototype") 注解,使 Spring 容器在需要时为每个请求创建一个新的 Bean 实例。这将使每个线程都拥有它自己的 Bean 实例,从而避免线程安全问题。此外,你还可以使用 Spring 提供的其他作用域,例如 @Scope("request") 或 @Scope("session") 等。
​
对于那些需要在多个请求或线程之间共享状态的 Bean,你应该采取措施来确保线程安全。例如,你可以使用同步锁或并发集合,或者使用线程安全的设计模式来编写 Bean 的代码。
7.Spring 支持几种 bean 的作用域?
答案:Spring支持五种bean的作用域,分别是单例(Singleton)、原型(Prototype)、会话 (Session)、请求(Request)和全局会话(Global Session)。
---------------------------------------------------------------------------------------
Spring 框架支持以下几种常用的 Bean 作用域:
​
Singleton(单例):这是默认的作用域。Spring 容器只会创建一个该类型的 Bean 实例,并在需要时重用它。单例的 Bean 在整个应用程序中是共享的。
​
Prototype(原型):每次请求时都会创建一个新的 Bean 实例。这意味着每次从容器中获取该类型的 Bean 实例时,都会得到一个新的对象。原型的 Bean 是非共享的。
​
Request(请求):每个 HTTP 请求都会创建一个新的 Bean 实例,该实例仅在当前请求的范围内有效。这意味着在同一次请求中多个地方获取该类型的 Bean 实例时,会得到同一个对象。
​
Session(会话):每个用户会话创建一个新的 Bean 实例,该实例仅在用户会话范围内有效。在同一个用户会话中获取该类型的 Bean 实例时,会得到同一个对象。
​
Global Session(全局会话):类似于会话作用域,但适用于基于 Portlet 的 Web 应用程序。在 Portlet 环境中,全局会话的作用域是跨多个 Portlet 的会话。
​
此外,Spring 还提供了一些其他的自定义作用域,如自定义线程作用域(Thread Scope)和自定义作用域(Custom Scope),你可以根据自己的需求来定义和使用这些作用域。
​
你可以使用 @Scope 注解来为 Bean 显式地指定作用域,或者在 Spring 配置文件中使用 <scope> 元素进行配置。
8.Spring 自动装配 bean 有哪些方式?
答案:Spring自动装配bean有三种方式,分别是no(默认不自动装配)、byName(根据属性名自动装配)和byType(根据属性类型自动装配)。
---------------------------------------------------------------------------------------
Spring 框架提供了以下几种方式来实现自动装配(Autuwiring)Bean:
​
默认的自动装配:默认情况下,Spring 容器会根据类型自动将合适的 Bean 注入到目标对象中。如果目标类中存在一个唯一的匹配类型的 Bean,则自动将其注入。
​
根据类型自动装配:使用 @Autowired 注解将依赖项直接注入到目标对象中。Spring 容器会根据类型自动查找匹配的 Bean 并注入。
​
示例:

​
public class MyClass {
    @Autowired
    private MyDependency myDependency;
}
根据名称自动装配:使用 @Autowired 注解结合 @Qualifier 注解,通过指定 Bean 的名称来进行装配。如果存在多个匹配类型的 Bean,可以使用 @Qualifier 注解指定要注入的 Bean 的名称。
示例:
​

public class MyClass {
    @Autowired
    @Qualifier("myDependencyBean")
    private MyDependency myDependency;
}
构造函数自动装配:使用 @Autowired 注解标记在构造函数上,Spring 容器会通过构造函数将合适的 Bean 注入到目标对象中。如果只有一个构造函数,可以省略 @Autowired 注解。
示例:
​

public class MyClass {
    private MyDependency myDependency;
​
    @Autowired
    public MyClass(MyDependency myDependency) {
        this.myDependency = myDependency;
    }
}
使用 @Resource 注解:@Resource 注解支持根据名称和类型进行自动装配。它可以通过指定 name 属性来根据 Bean 的名称进行装配,也可以通过根据类型进行装配。
示例:
​

public class MyClass {
    @Resource(name = "myDependencyBean")
    private MyDependency myDependency;
}
无论选择哪种自动装配方式,Spring 都会根据指定的装配规则自动解析依赖并完成装配。你可以根据具体的需求选择合适的自动装配方式。
9.Spring 事务实现方式有哪些?
答案:Spring事务实现方式包括编程式事务管理和声明式事务管理。声明式事务管理可以基于XML配置或基于注解。
---------------------------------------------------------------------------------------
Spring 框架提供了多种方式来实现事务管理:
​
编程式事务管理:通过编写代码来管理事务,需要手动开始、提交、回滚事务。Spring 提供了 TransactionTemplate 类和 PlatformTransactionManager 接口来支持编程式事务管理。你可以在需要事务管理的方法中使用 TransactionTemplate或PlatformTransactionManager 来控制事务的开始、提交、回滚等操作。
示例:
​

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}
​
@Autowired
private PlatformTransactionManager transactionManager;
​
public void doSomething() {
    TransactionStatus txStatus = transactionManager.getTransaction();
    try {
        // 事务操作
        transactionManager.commit(txStatus);
    } catch (Exception ex) {
        transactionManager.rollback(txStatus);
    }
}
声明式事务管理:通过配置声明来管理事务,不需要显式编写代码来控制事务,可以将事务配置放在配置文件或使用注解的方式来定义事务的行为。Spring 提供了 @Transactional 注解来支持声明式事务管理。你可以在需要事务管理的方法或类上添加 @Transactional 注解,指定事务的属性(如隔离级别、传播行为、回滚规则等)。
示例:
​

@Transactional
public void doSomething() {
    // 事务操作
}
XML 配置方式:可以使用 XML 配置文件来定义事务的属性和行为。通过配置 <tx:advice>、<tx:attributes> 等 XML 元素来指定方法的事务操作。
示例:
​

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="doSomething" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
​
<aop:config>
    <aop:pointcut expression="execution(* com.example.service.*.*(..))" id="txPointcut"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>
以上是 Spring 框架中实现事务管理的常见方式。你可以根据具体的需求选择合适的方式来管理事务。同时,Spring 还支持与各种持久化框架(如 Hibernate、JPA)集成进行事务管理。
10.说一下 Spring 的事务隔离?
答案:Spring的事务隔离级别包括READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ和SERIALIZABLE。不同的隔离级别决定了事务之间的可见性和并发性。
---------------------------------------------------------------------------------------
Spring 提供了与数据库事务隔离级别对应的五个枚举常量来定义事务的隔离级别:
​
DEFAULT(默认值):使用底层数据库的默认隔离级别。
​
READ_UNCOMMITTED:最低的事务隔离级别。允许读取未提交的修改。存在脏读、不可重复读和幻读的问题。
​
READ_COMMITTED:允许读取已提交的修改。避免了脏读问题,但仍可能出现不可重复读和幻读的问题。
​
REPEATABLE_READ:对同一数据的读取是一致的,多次读取返回相同的结果。避免了脏读和不可重复读问题,但仍可能出现幻读的问题。
​
SERIALIZABLE:最高的事务隔离级别。完全禁止并发操作,保证事务之间的串行执行。避免了脏读、不可重复读和幻读的问题,但对性能有一定影响。
​
你可以通过在方法上使用 @Transactional 注解或在 XML 配置中设置 transactional 属性来指定事务的隔离级别。例如:
​

@Transactional(isolation = Isolation.READ_COMMITTED)
public void doSomething() {
    // 事务操作
}
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="doSomething" isolation="READ_COMMITTED"/>
    </tx:attributes>
</tx:advice>
需要注意的是,事务隔离级别是由数据库实现的,不同的数据库可能会有稍微不同的行为。此外,过高的隔离级别会增加锁的粒度,导致并发性能下降,因此在选择事务隔离级别时需要根据具体情况进行权衡。
11.说一下 Spring MVC 运行流程?
答案:Spring MVC的运行流程包括请求的分发、处理器映射、处理器适配、处理器执行、视图解 析、视图渲染等步骤。
---------------------------------------------------------------------------------------
Spring MVC 是一个基于 Java 的 Web 框架,它采用了 MVC(Model-View-Controller)的设计模式来实现 Web 应用程序的开发。下面是 Spring MVC 的运行流程:
​
客户端发送请求:用户通过浏览器发送请求到服务器,请求可以是一个 URL,包含了请求的方法(GET、POST 等)、参数、请求头等信息。
​
DispatcherServlet 接收请求:所有的请求都会先到达 Spring MVC 的中央控制器 DispatcherServlet。它是 Spring MVC 的核心组件,负责接收和分发请求。
​
处理器映射器(Handler Mapping)匹配处理器:DispatcherServlet 通过处理器映射器来确定请求对应的处理器(即控制器)。处理器映射器根据请求的 URL 或其他条件来匹配合适的处理器。
​
处理器执行处理逻辑:匹配到合适的处理器之后,DispatcherServlet 会调用处理器来执行实际的业务逻辑。处理器可以是一个带有 @Controller 注解的类或其他实现了 Handler 接口的类。
​
视图解析器(View Resolver)解析视图名:处理器执行完业务逻辑后,通常会返回一个逻辑视图名,该视图名表示要展示给用户的视图。视图解析器会根据逻辑视图名解析出对应的真正视图对象,通常是一个 JSP、HTML 或其他模板引擎中的模板文件。
​
视图渲染:视图解析器解析出视图对象后,DispatcherServlet 会将模型数据传递给视图对象,并由视图对象进行渲染处理。视图可以根据模型数据生成 HTML、JSON、XML 等响应内容。
​
返回响应:视图渲染完毕后,DispatcherServlet 将最终生成的响应内容返回给客户端。响应内容可以是一个 HTML 页面、一个 JSON 数据串等。
​
这只是 Spring MVC 的核心流程,实际上,Spring MVC 还包含了各种机制和组件,如拦截器(Interceptor)、数据绑定、类型转换等,它们提供了更多的功能和灵活性来进行 Web 应用程序的开发。
12.Spring MVC 有哪些组件?
答案:Spring MVC包括控制器(Controller)、处理器映射(Handler Mapping)、处理器适配 (Handler Adapter)、视图解析器(View Resolver)等组件。
---------------------------------------------------------------------------------------
Spring MVC 框架由以下几个主要的组件组成:
​
DispatcherServlet(派发器):作为前端控制器(Front Controller),接收客户端的请求,并将请求分发给相应的处理器。
​
HandlerMapping(处理器映射器):负责将请求映射到对应的处理器(即控制器)。处理器映射器根据请求的 URL 或其他条件来确定合适的处理器。
​
Controller(控制器):处理器的实现类,负责处理请求并生成响应。可以是一个带有 @Controller 注解的类,或者实现了 Controller 接口的类。
​
HandlerAdapter(处理器适配器):用于调用处理器的适配器,使得不同类型的处理器能够适配到统一的处理器执行方式。
​
HandlerInterceptor(处理器拦截器):拦截器可以在请求的各个阶段进行预处理和后处理操作。可以实现自定义的拦截器来添加业务逻辑、权限验证、日志记录等功能。
​
ViewResolver(视图解析器):负责解析逻辑视图名并转换为真正的视图对象,例如 JSP、Thymeleaf、FreeMarker 等。可以根据视图对象渲染输出内容。
​
View(视图):负责将模型数据渲染为最终的响应内容,例如生成 HTML 页面、JSON 数据串等。
​
ModelAndView(模型和视图对象):封装处理器处理结果模型数据和视图名称的对象,便于处理器方法返回多个数据类型。
​
DataBinder(数据绑定器):将用户提交的请求参数绑定到处理器方法的参数或表单对象上。
​
HandlerExceptionResolver(处理器异常解析器):用于处理处理器执行过程中产生的异常,并返回适当的错误响应。
​
这些组件共同协作,实现了 Spring MVC 框架的核心功能,提供了灵活且可扩展的方式来构建 Web 应用程序。
13.@RequestMapping 的作用是什么?
答案:@RequestMapping是Spring MVC中的注解,用于映射请求路径到处理方法,指定请求的HTTP方法、路径等。
---------------------------------------------------------------------------------------
@RequestMapping 是 Spring MVC 提供的注解,用于将 URL 映射到处理器方法上,定义请求的映射规则。其作用主要有以下几点:
​
URL 映射:@RequestMapping 可以用在类级别和方法级别上。在类级别上使用,可以定义处理器的根路径,使得所有处理器方法都能匹配到以该路径开始的请求。在方法级别上使用,可以进一步细化请求的映射规则,可以根据请求的路径、请求参数、请求方法等进行更精确的匹配。
​
请求方法映射:@RequestMapping 可以指定处理器方法能处理的请求方法,如 GET、POST、PUT、DELETE 等。通过指定请求方法可以对不同的请求进行不同的处理。默认情况下,处理器方法可以处理所有方法的请求。
​
请求参数匹配:@RequestMapping 可以通过指定请求参数、请求头、请求内容类型等条件,对请求进行更精确的匹配。例如,可以根据请求参数的值、请求头的值等来决定是否匹配到该处理器方法。
​
RESTful 风格支持:@RequestMapping 支持使用占位符和正则表达式来定义动态的 URL。这样可以实现 RESTful 风格的 URL,例如 /user/{id},其中 {id} 表示一个可变的路径参数。
​
路径变量绑定:@RequestMapping 也可以用于将 URL 路径中的变量绑定到处理器方法的参数上。通过在 @PathVariable 注解中指定路径变量的名称,Spring MVC 可以自动将 URL 路径中的变量值传递给处理器方法的参数。
​
总而言之,@RequestMapping 提供了一种灵活且强大的方式,将请求和处理器方法进行映射,能够精确控制请求的处理流程。
14.@Autowired 的作用是什么?
答案:@Autowired是Spring的注解,用于自动装配bean的属性,可以实现依赖注入,避免手动创建和设置对象。
---------------------------------------------------------------------------------------
@Autowired 是 Spring 提供的注解,用于自动装配(注入)依赖对象。其作用主要有以下几点:
​
自动装配:@Autowired 可以通过类型匹配自动查找到应该注入的依赖对象,并将其自动装配到需要的地方。不需要手动创建和管理依赖对象的实例。
​
依赖注入:@Autowired 可以将被注解的字段、构造方法或者方法参数与对应的依赖对象关联起来。当容器创建对象时,会自动解析并注入相应的依赖对象。
​
依赖对象查找:如果无法通过类型匹配找到唯一的依赖对象时,@Autowired 也可以通过 @Qualifier 注解指定具体的依赖对象名称。
​
依赖对象生命周期管理:@Autowired 注解可以与其他生命周期注解结合使用,如 @PostConstruct、@PreDestroy 等,实现对依赖对象的初始化和销毁操作。
​
简化配置:使用 @Autowired 注解可以减少 XML 配置文件中的配置内容,简化配置,提高开发效率。
​
需要注意的是,@Autowired 注解默认使用的是按照类型进行依赖注入,如果存在多个匹配类型的依赖对象,会抛出异常。可以通过 @Qualifier 注解或者 @Primary 注解来解决多个依赖对象的问题,或者使用 @Autowired(required = false) 来指定依赖对象为可选的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值