2023新版Spring6全新讲解-核心内容之IoC

news2024/10/7 16:18:42

在这里插入图片描述

Spring核心之IoC

image.png

一、IoC概念介绍

1.IoC 介绍

  IoC 是 Inversion of Control 的简写,译为“控制反转”,它不是一门技术,而是一种设计思想,是一个重要的面向对象编程法则,能够指导我们如何设计出松耦合、更优良的程序。

  Spring 通过 IoC 容器来管理所有 Java 对象的实例化和初始化,控制对象与对象之间的依赖关系。我们将由 IoC 容器管理的 Java 对象称为 Spring Bean,它与使用关键字 new 创建的 Java 对象没有任何区别。

  IoC 容器是 Spring 框架中最重要的核心组件之一,它贯穿了 Spring 从诞生到成长的整个过程。

image.png

控制反转,反转的是什么?

image.png

控制反转这种思想如何实现呢?

image.png

  有些情况下我们认为IoC包含了DI。当然我们也可以分开来看。

2.DI 介绍

  DI(Dependency Injection):依赖注入,依赖注入实现了控制反转的思想。

指Spring创建对象的过程中,将对象依赖属性通过配置进行注入

依赖注入常见的实现方式包括两种:

image.png

通过上面的介绍我们可以这么理解IoC和DI的关系

  • IoC是一种控制反转的思想
  • DI是对IoC的一种具体实现

相对于Bean的管理来说。IoC和DI要做的事情就是Bean对象的创建、以及Bean对象中属性的赋值(或者是相互间的关系维护)。

3. Spring中的IoC实现

image.png

  Spring 的 IoC 容器就是 IoC思想的一个落地的产品实现。IoC容器中管理的组件也叫做 bean。在创建 bean 之前,首先需要创建IoC 容器。Spring 提供了IoC 容器的两种实现方式:

BeanFactory

这是 IoC 容器的基本实现,是 Spring 内部使用的接口。面向 Spring 本身,不提供给开发人员使用。

ApplicationContext

BeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎所有场合都使用 ApplicationContext 而不是底层的 BeanFactory。

ApplicationContext的主要实现类:

类型名简介
ClassPathXmlApplicationContext通过读取类路径下的 XML 格式的配置文件创建 IOC 容器对象
FileSystemXmlApplicationContext通过文件系统路径读取 XML 格式的配置文件创建 IOC 容器对象
ConfigurableApplicationContextApplicationContext 的子接口,包含一些扩展方法 refresh() 和 close() ,让 ApplicationContext 具有启动、关闭和刷新上下文的能力。
WebApplicationContext专门为 Web 应用准备,基于 Web 环境创建 IOC 容器对象,并将对象引入存入 ServletContext 域中。

image.png

二、基于XML的方式

1.搭建案例项目

  和前面的入门案例的步骤是一样的,创建项目,添加相关依赖和引入对应的配置文件。

<dependencies>
        <!--spring context依赖-->
        <!--当你引入Spring Context依赖之后,表示将Spring的基础依赖引入了-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.27</version>
        </dependency>

        <!--junit5测试-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.3.1</version>
        </dependency>
        <!--log4j2的依赖-->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j2-impl</artifactId>
            <version>2.19.0</version>
        </dependency>
    </dependencies>

2. 获取Bean的方式

2.1 根据ID类获取

  我们可以通过在Bean 标签中定义的id属性来获取IoC容器中的对象,id属性具有唯一性。我们可以通过id精确的找到唯一的对象。

<bean id="helloWorld" class="com.boge.spring.HelloWorld"></bean>

具体的单元测试代码

    @Test
    public void test1(){
        // 1.获取Spring的IoC容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
       // 2.根据定义的id来从IoC容器中获取Bean的对象 快捷键 Alt + Enter
        HelloWorld helloWorld = (HelloWorld) ac.getBean("helloWorld");
        helloWorld.sayHello();
        logger.info("通过ID获取Bean对象");
    }

2.2 根据类型获取

  我们通过id或者name获取是获取到的一个Object对象。我们需要自己强制类型转换,我们还可以根据需要获取的类型中IoC容器中获取我们的对象。

    /**
     * 根据类型属性来获取
     */
    @Test
    public void test3(){
        // 1.获取Spring的IoC容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        // 2.根据定义的id来从IoC容器中获取Bean的对象 快捷键 Alt + Enter
        HelloWorld helloWorld = ac.getBean(HelloWorld.class);
        helloWorld.sayHello();
        logger.info("通过Class获取Bean对象");
    }

通过类型来获取Bean对象。那么有个问题需要注意。如果IoC容器中有多个相同类型的Bean对象。那么我们直接通过类型来获取就会有问题。

image.png

然后我们再获取的时候就会提示异常信息

image.png

那么针对于这种情况我们的解决方案如下:

2.3 根据Id和类型获取

  上面的情况中相同类型的Bean对象在IoC容器中有多个。直接获取会抛出异常信息。这时我们可以通过组合的方式来获取,也就就通过id+class的方式来获取。

    /**
     * 根据Id + 类型属性来获取
     */
    @Test
    public void test4(){
        // 1.获取Spring的IoC容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("ApplicationContext.xml");
        // 2.根据定义的id+类型从IoC容器中获取Bean的对象 快捷键 Alt + Enter
        HelloWorld helloWorld = ac.getBean("helloWorld1",HelloWorld.class);
        helloWorld.sayHello();
        logger.info("通过Class获取Bean对象");
    }

3. 依赖注入之setter

  我们前面的案例都只是直接创建了一个对象。并没有对相关的属性做对应的操作。我们可以通过依赖注入来完成相关的属性的初始化。我们可以创建一个简单的Bean。

package com.boge.spring.bean;

public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private String gender;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

然后我们的配置文件中通过 property标签来完成setter注入:

    <!-- 我们可以通过setter来完成属性的赋值操作 -->
    <bean id="student1" class="com.boge.spring.bean.Student">
        <!--
            property标签:通过Bean中定义的setter方法来给组件做赋值
            name属性:指定的属性名称。setXxx() 方法来完成赋值
            value属性:setXxx(value) 属性值
         -->
        <property name="id" value="1"></property>
        <property name="name" value="波哥"></property>
        <property name="age" value="18"></property>
        <property name="gender" value="" ></property>
    </bean>

然后对应的执行效果

image.png

在这儿需要注意。对应的属性我们必须要提供setter方法。

image.png

4. 依赖注入之构造注入

  针对上面的设置注入中的必要条件是对应的属性必须添加相关的setter方法。我们可以通过构造注入的方式来解决。

package com.boge.spring.bean;

public class User {

    private Integer id;

    private String name;

    private Integer age;

    private String gender;

    public User(Integer id, String name, Integer age, String gender) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
    }

    public User() {
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                '}';
    }
}

然后我们在配置文件中定义

<bean class="com.boge.spring.bean.User">
        <!--
            构造注入的实现
            constructor-arg标签:表示了对应Bean中的构造选项
        -->
        <!--<constructor-arg value="10086"></constructor-arg>
        <constructor-arg value="boge"></constructor-arg>
        <constructor-arg value="20"></constructor-arg>
        <constructor-arg value="女"></constructor-arg>-->
        <!-- name属性:指定的就是构造方法中的属性名称 -->
        <!--<constructor-arg name="id" value="10086"></constructor-arg>
        <constructor-arg name="name" value="boge"></constructor-arg>
        <constructor-arg name="age" value="20"></constructor-arg>
        <constructor-arg name="gender" value="女"></constructor-arg>-->
        <!-- index:表示该属性在构造方法中的位置。从0开始 -->
        <constructor-arg index="0" value="10086"></constructor-arg>
        <constructor-arg index="1" value="boge"></constructor-arg>
        <constructor-arg index="2" value="20"></constructor-arg>
        <constructor-arg index="3" value=""></constructor-arg>

    </bean>

然后对应的执行效果

image.png

5. 特殊值处理

5.1 null值

  针对属性赋值中的null的处理。我们不能直接在value中赋值。需要通过 标签来处理

image.png

5.2 xml实体

   针对我们赋值中有的特殊符号。比如 < > 等。xml文件解析的时候会作为xml中的组成部分来解析。这时我们可以通过 xml实体或者CDATA来解决

image.png

6. 对象类型赋值

6.1 引用外部Bean

  我们可以通过ref属性来引入我们在配置文件中定义的外部Bean对象。

<bean class="com.boge.spring.bean2.Clazz" id="clazz">
        <property name="classId" value="1001"></property>
        <property name="className" value="软件1班"></property>
    </bean>

    <bean class="com.boge.spring.bean2.Student" id="student1">
        <property name="id" value="18"></property>
        <property name="name" value="波哥"></property>
        <property name="clazz" ref="clazz"></property>
    </bean>

6.2 内部定义Bean

  当然如果我们需要赋值的Bean仅仅只是在当前的Bean中需要使用到。那么我们还可以直接在property标签的内部通过bean标签来定义要赋值的Bean

    <bean class="com.boge.spring.bean2.Student" id="student2">
        <property name="id" value="18"></property>
        <property name="name" value="波哥"></property>
        <property name="clazz" >
            <!-- 在一个bean的内部我们再声明一个内部bean -->
            <bean class="com.boge.spring.bean2.Clazz">
                <property name="classId" value="1002"></property>
                <property name="className" value="软件2班"></property>
            </bean>
        </property>
    </bean>

6.3 级联赋值

  针对需要赋值的自定义对象我们可以通过对象属性加 . 存取器来实现级联属性的赋值操作

<bean class="com.boge.spring.bean2.Student" id="student3">
        <property name="id" value="18"></property>
        <property name="name" value="波哥"></property>
        <property name="clazz" ref="clazz"></property>
        <!-- 级联属性赋值 -->
        <property name="clazz.classId" value="1003"></property>
        <property name="clazz.className" value="软件3班" ></property>
    </bean>

    <bean class="com.boge.spring.bean2.Student" id="student4">
        <property name="id" value="18"></property>
        <property name="name" value="波哥"></property>
        <property name="clazz" >
            <!-- 在一个bean的内部我们再声明一个内部bean -->
            <bean class="com.boge.spring.bean2.Clazz">
            </bean>
        </property>
        <property name="clazz.classId" value="1004"></property>
        <property name="clazz.className" value="软件5班" ></property>
    </bean>

7. 数组类型赋值

  注入到容器中的Bean的属性中可能是数组类型。那么这时我们可以通过array标签来完成赋值

image.png

8. 集合类型赋值

  注入到容器中的Bean的属性可能是List集合。那么我们需要通过list标签来完成属性的赋值

image.png

当然上面的例子我们的List的属性是String类型。那么List的类型也可能是自定义类型。那么处理方式和前面的是一致的。

<bean class="com.boge.spring.bean3.Classzz" id="classzz">
        <property name="id" value="1001"></property>
        <property name="classzzName" value="软件1班"></property>
        <property name="stus" >
            <list>
                <ref bean="student1"></ref>
                <bean class="com.boge.spring.bean3.Student"></bean>
            </list>
        </property>
    </bean>

集合中我们还有一种情况是Map集合

        <property name="map">
            <map>
                <entry>
                    <key>
                        <value>张三</value>
                    </key>
                    <value>18</value>
                </entry>
                <entry>
                    <key>
                        <value>李四</value>
                    </key>
                    <value>22</value>
                </entry>
            </map>
        </property>

我们可以通过util标签来定义外部的集合数据。然后通过ref来引用就可以了。但是我们需要先声明util的schema。

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

然后具体的使用操作

image.png

9. p命名空间

  简化属性的赋值操作

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 外部定义的集合数据 -->
    <util:list id="studentHobbies">
        <value >h1</value>
        <value >h2</value>
        <value >h3</value>
    </util:list>
   <!-- p 属性 简化属性的赋值操作 -->
   <bean class="com.boge.spring.bean4.Student" id="student1"
         p:id="666" p:name="波哥" p:hobbies2-ref="studentHobbies"></bean>

</beans>

10. 外部属性文件

  为了实现配置信息内容的共享。我们可以把一些共享的信息单独的配置在一个独立的properties文件中。然后通过context标签来引入。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util.xsd
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 引入外部的属性文件 -->
    <context:property-placeholder location="classpath:myProperties.properties"></context:property-placeholder>

    <!-- 外部定义的集合数据 -->
    <util:list id="studentHobbies">
        <value >${user.hobbies.h1}</value>
        <value >${user.hobbies.h2}</value>
        <value >h3</value>
    </util:list>
   <!-- p 属性 简化属性的赋值操作 -->
   <bean class="com.boge.spring.bean4.Student" id="student1"
         p:id="666" p:name="波哥" p:hobbies2-ref="studentHobbies"></bean>

</beans>

具体的步骤:

  1. 定义属性文件
  2. 添加context标签的schema
  3. 通过context中的 property-placeholder引入属性文件
  4. 然后通过${}表达式来使用属性文件中什么的信息

11.案例练习

  首先结合前面的步骤创建一个新的maven项目。完成基本的spring的配置。然后添加Bean实体

public class User {

    private Integer id;

    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

然后创建Dao的接口和实现类

/**
 * 持久层定义的接口
 */
public interface IUserDao {

    public List<User> query();
}

public class UserDaoImpl implements IUserDao {
    @Override
    public List<User> query() {
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            User user = new User();
            user.setId(i);
            user.setName("boge"+i);
            list.add(user);
        }
        return list;
    }
}

然后创建Service层的接口和实现类。我们在service中获取Dao的实现是通过设值注入来完成的

public interface IUserService {

    public List<User> querUser();
}
public class UserServiceImpl implements IUserService {
    // 声明 dao 需要通过设置注入或者构造注入来实现
    private IUserDao dao ;

    @Override
    public List<User> querUser() {
        return dao.query();
    }

    public void setDao(IUserDao dao) {
        this.dao = dao;
    }
}

  然后创建Controller层,需要获取的Service我们通过构造注入完成依赖

/**
 * 控制器
 */
public class UserController {

    // 也需要我们通过构造或者设值注入  此处我们通过构造注入来完成
    private IUserService userService;

    public void queryList(){
        List<User> users = userService.querUser();
        for (User user : users) {
            System.out.println(user);
        }
    }

    public UserController(IUserService userService) {
        this.userService = userService;
    }
}

上面的基本代码完成后我们在配置文件中完成相关的配置信息

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 注入相关的对象 -->
    <bean class="com.boge.spring.dao.impl.UserDaoImpl" id="userDao"></bean>

    <bean class="com.boge.spring.service.impl.UserServiceImpl" id="userService">
        <!-- 通过设值注入Dao -->
        <property name="dao" ref="userDao"></property>
    </bean>

    <bean class="com.boge.spring.controller.UserController" id="userController">
        <!-- 通过构造注入完成service依赖管理 -->
        <constructor-arg name="userService" ref="userService"></constructor-arg>
    </bean>
</beans>

最后完成测试

    /**
     * 案例测试
     */
    @Test
    public void test1(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
        UserController bean = ac.getBean(UserController.class);
        bean.queryList();
    }

执行效果

image.png

三、基于注解的方式

  Spring 从 2.5 版本开始提供了对注解技术的全面支持,我们可以使用注解来实现自动装配,简化 Spring 的 XML 配置。

Spring 通过注解实现自动装配的步骤如下:

  1. 引入依赖
  2. 开启组件扫描
  3. 使用注解定义 Bean
  4. 依赖注入

1. 搭建案例项目

  和上面的操作是一样的。

2. 开启扫描

  开启扫描需要添加context的schema。然后通过context:componment-scan 来指定扫描的路径

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!--
        1.引入 context 的schema
        2.开启扫描
        3.通过相关的注解实现注入
     -->
    <!-- 放开扫描 -->
    <context:component-scan base-package="com.boge.spring.entity"></context:component-scan>

</beans>

上面的扫描指定的路径是 com.boge.spring.entity 那么项目启动的时候就会去这个包下面加载所有被@Component 注解修饰的Java类。

3. 注解标识

在需要被Spring注入的类的头部添加@Compnent 注解

image.png

  

4. 案例测试

  编写测试案例。完成逻辑校验

    @Test
    public void test1(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("application.xml");
        User bean = ac.getBean(User.class);
        System.out.println(bean);
    }

对应的执行效果

image.png

5.依赖注入问题

  在上面的案例中。我们的controller service dao我们都可以通过@Component注解来完成对象的注入。但是controller对service的依赖,service对Dao的依赖。也就是 设值注入和构造注入是不能使用的。这时候我们可以通过@Autowired注解来解决这个问题

image.png

image.png

测试通过

image.png

6. 接口注入

  上面我们虽然通过@Autowried注解解决了属性的依赖注入问题。但是在我们的实体中还是需要添加对应的setter和构造方法。会显得整个的代码结构不太简洁,这时我们可以通过接口注入的方式来处理。

image.png

image.png

7. 注解的多样性

  Spring 提供了以下多个注解,这些注解可以直接标注在 Java 类上,将它们定义成 Spring Bean。

注解说明
@Component该注解用于描述 Spring 中的 Bean,它是一个泛化的概念,仅仅表示容器中的一个组件(Bean),并且可以作用在应用的任何层次,例如 Service 层、Dao 层等。 使用时只需将该注解标注在相应类上即可。
@Repository该注解用于将数据访问层(Dao 层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service该注解通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller该注解通常作用在控制层(如SpringMVC 的 Controller),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

image.png

image.png

image.png

8.Autowired注解

  @Autowired注解作用是完成对应的Bean依赖注入。

@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
	 * Declares whether the annotated dependency is required.
	 * <p>Defaults to {@code true}.
	 */
	boolean required() default true;

}

通过源码的查看我们可以发现@Autowired注解的作用位置

  • 构造方法–构造注入
  • 方法上–setter方法上完成设值注入
  • 形参上–接口注入
  • 属性上
  • 注解上

还有就是在源码中有一个 required 抽象方法。表示注入的bean是否是必须的。默认为true,表示在注入的bean必须是存在,如果不存在就报错,如果required设值为false。如果不存在就不会报错。

image.png

当我们的形参只有一个的情况下 @Autowired 注解可以省略

image.png

@Autowired注解可以和@Qualifier注解一块去使用。@Autowired注解默认是基于类型类完成Bean的依赖注入的

image.png

针对这种情况。@Qualifier 可以实现基于name的查找注入

image.png

简单总结:

  1. @Autowired注解可以出现的位置:属性上,方法上,构造方法上,形参上,注解上
  2. 当带有参数的构造方法只有一个的情况下。@Autowired注解可以省略
  3. @Autowired注解默认是根据类型来注入的,如果要根据名称来注入。我们需要配置@Qualifier注解来实现

9.综合案例

  对上面注解的方式的综合练习

/**
 * Lombok 插件。会帮助我们管理Bean的实体对象
 */
@Data
@AllArgsConstructor
public class UserEntity {

    private Integer id;

    private String userName;

}
@Repository
public class UserDaoImpl implements IUserDao {
    @Override
    public List<UserEntity> list() {
        List<UserEntity> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            UserEntity user = new UserEntity(i,"boge"+i);
            list.add(user);
        }
        return list;
    }
}
@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private IUserDao dao;

    @Override
    public List<UserEntity> list() {
        return dao.list();
    }
}
@Controller
public class UserController {

    @Autowired
    private IUserService userService;

    public void list(){
        System.out.println("---->");
        List<UserEntity> list = userService.list();

        for (UserEntity userEntity : list) {
            System.out.println(userEntity);
        }
    }
}

上面的业务代码完成后我们需要添加对应的配置文件。然后添加对应扫描路径即可

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 添加对应的扫描路径 -->
    <context:component-scan base-package="com.boge.*"></context:component-scan>
</beans>

然后测试即可

image.png

10 @Resource

@Resource注解也可以完成属性注入。那它和@Autowired注解有什么区别?

  • @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
  • @Autowired注解是Spring框架自己的。
  • @Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。
  • @Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。
  • @Resource注解用在属性上、setter方法上。
  • @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。

@Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【****如果是JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖。】

<dependency>
    <groupId>jakarta.annotation</groupId>
    <artifactId>jakarta.annotation-api</artifactId>
    <version>2.1.1</version>
</dependency>

image.png

11. 基于Java配置类的方式

  上面的介绍中基于注解的使用我们还是需要添加对应的配置文件。不是分方便。那么从Spring3.0开始提供的@Configuration注解。到Spring3.1 推出的@ComponentScan注解。那么我们完全可以脱离xml配置文件的使用方式了。

/**
 * Spring的配置类
 * 作用是替换调配置文件
 */
@Configuration // 加了这个注解 我们的这个配置类就相对于 applicationContext.xml 配置文件
@ComponentScan(basePackages = "com.boge")
public class SpringConfiguration {

}

@ComponentScan注解指定的扫描路径在启动的时候就会加载相关路径下的@Component注解修饰的Bean对象。然后我们也可以通过@Bean注解实现对象的注入操作

/**
 * Spring的配置类
 * 作用是替换调配置文件
 */
@Configuration // 加了这个注解 我们的这个配置类就相对于 applicationContext.xml 配置文件
@ComponentScan(basePackages = "com.boge")
public class SpringConfiguration {


    /**
     * 我们在相关的方法的头部添加 @Bean注解 可以实现讲改方法的返回对象注入到容器中
     * @return
     */
    @Bean
    public UserEntity userEntity(){
        UserEntity bean = new UserEntity(1, "波哥");
        return bean;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/569164.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何获得铁粉?

铁粉是指那些非常喜欢某个人、品牌、产品或组织的人群&#xff0c;他们对所支持的对象非常忠诚&#xff0c;会在各种场合下宣传、支持和捍卫他们的偶像。铁粉通常会在社交媒体上关注他们的偶像、分享他们的内容、购买他们的产品或服务&#xff0c;并与其他铁粉互动和交流。他们…

JavaScript中的生成器函数(Generator Functions)

简介&#xff1a; 生成器函数&#xff08;Generator Functions&#xff09;是JavaScript中的一种特殊类型函数&#xff0c;它允许开发者在函数内部产生多个值并逐步返回&#xff0c;与传统函数一次返回单个值的方式不同。本文将介绍生成器函数的特性、优缺点以及如何使用它们&a…

【重新定义matlab强大系列十】函数normalize进行归一化数据

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 #### 防伪水印——左手の明天 #### &#x1f497; 大家好&#x1f917;&#x1f91…

2. css表格属性、文本属性、列表属性、边距属性、尺寸属性

1. 表格属性 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width…

每日一题——四数之和(双指针解法)

每日一题 四数之和 注&#xff1a; 如果大家没做过题目两数之和、三数之和&#xff0c;强烈建议先去做做&#xff0c;也可以参考我之前写的博客&#xff0c;这样做这一题会事半功倍&#xff0c;且由于本题思路和三数之和十分类似&#xff0c;故对于解题思路&#xff0c;也不会…

涨点神器:注意力机制---多头上下文集成(Context Aggregation)的广义构建模块,助力小目标检测,暴力涨点

1.数据集性能验证 在crack道路缺陷检测任务中,多头上下文集成(Context Aggregation)的广义构建模块实现暴力涨点mAP50从0.954提升至0.992 🏆🏆🏆🏆🏆🏆Yolov5/Yolov7魔术师🏆🏆🏆🏆🏆🏆 ✨✨✨魔改网络、复现前沿论文,组合优化创新 🚀🚀🚀…

第一章.The Learning Problem

第一章.The Learning Problem 1.1 The Learning Problem 1.机器学习的概念&#xff1a; 机器学习就是机器从数据中总结经验。从数据中找出某种规律或者模型&#xff0c;并用他来解决某种实际问题。 2.机器学习的应用场景 1).事物本身存在某种潜在规律 2).某些问题难以使用普…

海豚调度器完全设置东八区

为了兼容全世界不同时区&#xff0c;默认情况下&#xff0c;海豚调度器使用的是 UTC 0 时区&#xff0c;包括保存到数据库表中的数据时区&#xff0c;以及展示到页面上的时区。 如果我们想在页面上看到东八区时间&#xff0c;则需要在页面上手动选择上海时区&#xff0c;如下图…

调优圣经:零基础精通Jmeter分布式压测,10Wqps+超高并发

高并发压测的场景 在40岁老架构师尼恩的读者社群&#xff08;50&#xff09;中&#xff0c;很多小伙伴拿不到offer&#xff0c;或者拿不到好的offer。 尼恩经常给大家 优化项目&#xff0c;优化简历&#xff0c;挖掘技术亮点。 在指导简历的过程中&#xff0c; Java 调优是一…

【Vue】一:Vue的基础

文章目录 1.第一个Vue程序1.1 创建Vue实例1.2 将Vue实例挂载到某个位置 2. 模板语句数据来源3. Vue实例的数据对象4. template配置项详解 1.第一个Vue程序 1.1 创建Vue实例 &#xff08;1&#xff09;创建Vue实例 创建一个Vue实例&#xff1a;new Vue() &#xff08;2&#x…

SpringCloud Sentinel集成Gateway和实时监控

目录 1 Sentinel集成Gateway1.1 Sentinel对网关支持1.2 GateWay集成Sentinel 2 Sentinel控制台2.1 Sentinel控制台安装2.2 接入控制台2.3 可视化管理2.3.1 实时监控2.3.2 流控规则2.3.3 降级规则2.3.4 热点数据 1 Sentinel集成Gateway 参看&#xff1a; https://github.com/al…

Linux网络编程——Day12 两种高效的并发模式

今天继续学习高性能服务器框架&#xff0c;上一篇关于高性能服务器的基础知识连接如下&#xff1a; Linux网络编程—Day11 高性能服务器程序框架_Jane_Librastar的博客-CSDN博客https://blog.csdn.net/qq_43797135/article/details/130834354建议先看上一篇哦~ 两种高效的并发…

就业内推 | 京东云专场,IP/NP以上证书,15薪,员工旅游

01 京东云 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1. 整体网络的部署和运维&#xff0c;包括网络新建、扩容、及变更等&#xff1b; 2. 保障网络及相关业务的稳定运行&#xff0c;对问题和故障进行跟踪并最终解决&#xff1b; 3. 与业务部门或客户密切配合&…

网络编程先导知识

目录 1.什么是网络协议 2.什么是Socket Socket主要类型 3.C/S和B/S架构 4.网络字节序和主机字节序 5.局域网和广域网 6.IP地址和端口的概念 1.什么是网络协议 为了在计算机网络中做到有条不紊地交换数据&#xff0c;就必须遵守一些事先约定好的规则。这些规则明确规定了所…

【P30】JMeter 事务控制器(Transaction Controller)

文章目录 一、事务控制器&#xff08;Transaction Controller&#xff09;参数说明二、测试计划设计2.2.1、勾选 Generate parent sample2.2.1、勾选 Include duration of timer and pre-post processors in generated sample 一、事务控制器&#xff08;Transaction Controlle…

Ubuntu22.04安装MySQL8

在 Ubuntu 22.04 上安装 MySQL 8&#xff0c;可以按照以下步骤进行&#xff1a; 安装MySQL需要在root用户下 sudo su -更新软件包列表&#xff1a; sudo apt update安装 MySQL 8&#xff1a; sudo apt install mysql-server安装过程中会提示设置 MySQL root 用户的密码。 确认…

STL-函数对象

目录 一、函数对象 1、基本概念 2、使用 二、谓词 1、基本概念 2、一元谓词 3、二元谓词 三、内建函数对象 1、基本概念 2、算数仿函数 3、关系仿函数 4、逻辑仿函数 一、函数对象 1、基本概念 概念&#xff1a; ①重载函数调用操作符的类&#xff0c;其对象常称…

关于Sql 中 on和where的粗略理解

先看到题&#xff1a;统计复旦用户8月练题情况 牛客中的 原地址 通过这个题我们来探讨where和on 描述 题目&#xff1a; 现在运营想要了解复旦大学的每个用户在8月份练习的总题目数和回答正确的题目数情况&#xff0c;请取出相应明细数据&#xff0c;对于在8月份没有练习过的…

【Ansys Fluent】All cell zones in Fluent may be automatically set to Fluid.

一、问题背景 在ansys meshing中保存划分完网格之后的结果时&#xff0c;弹出警报——All cell zones in Fluent may be automatically set to Fluid. 如果你忽视这个警报&#xff0c;打开fluent时。 接着就会将你想要设置为solid的区域识别成flow&#xff0c;从而生成一些错…

docker4_创建容器

docker4_搭建hadoop集群 1集群规划进入容器base_centos 2创建容器创建三个docker容器&#xff0c;分别作为三个结点(注意端口的设置)gpb_hdp_node3 容器gpb_hdp_node2 容器删除容器查看已经创好的容器gpb_hdp_node1容器&#xff08;最后创建&#xff09;问题1:容器名和 hostnam…