⭐表示重要。

第一章:标记和扫描(⭐)

1.1 注解的作用

1.1.1 注解

  • 注解和 XML 配置文件一样,注解本身并不能执行,注解本身仅仅只是做了一个标记,具体的功能是框架检测到注解标记的位置,然后针对这个位置按照注解标记的功能来执行具体的操作。
  • 本质上,所有的一切操作都是Java代码来完成的,XML 和注解只是告诉框架中的 Java 代码如何执行。

1.1.2 扫描

  • Spring 为了知道程序员在哪些地方标记了什么注解,就需要通过扫描的方式,来进行检测,然后根据注解进行后续操作。

1.2 环境准备

  • JDK 11+。
  • IDEA 2021+。
  • Maven 3.8。

1.3 导入依赖

  • pom.xml
  1. <!-- Spring -->
  2. <dependency>
  3. <groupId>org.springframework</groupId>
  4. <artifactId>spring-context</artifactId>
  5. <version>5.3.12</version>
  6. </dependency>
  7. <!-- junit单元测试 -->
  8. <dependency>
  9. <groupId>junit</groupId>
  10. <artifactId>junit</artifactId>
  11. <version>4.13.2</version>
  12. </dependency>

1.4 创建组件类

1.4.1 使用 @Component 注解标记的普通组件

  • 示例:
  1. package com.github.fairy.era.component;
  2. import org.springframework.stereotype.Component;
  3. /**
  4. * @author 许大仙
  5. * @version 1.0
  6. * @since 2021-11-05 14:26
  7. */
  8. @Component // 表明这是一个普通的组件
  9. public class HelloComponent {
  10. }

1.4.2 使用 @Controller 注解标记的控制器组件

  • 这个组件就是三层架构(表现层、业务逻辑层、数据访问层)中的表现层,即控制器,相当于 JavaWeb 阶段的Servlet。

  • 示例:

  1. package com.github.fairy.era.controller;
  2. import org.springframework.stereotype.Controller;
  3. /**
  4. * @author 许大仙
  5. * @version 1.0
  6. * @since 2021-11-05 14:28
  7. */
  8. @Controller // 表明这是一个控制器组件
  9. public class HelloController {
  10. }

1.4.3 使用 @Service 注解标记的业务逻辑组件

  • 这个组件就是三层架构(表现层、业务逻辑层、数据访问层)中的业务逻辑组件。

  • 示例:

  1. package com.github.fairy.era.service;
  2. import org.springframework.stereotype.Service;
  3. /**
  4. * @author 许大仙
  5. * @version 1.0
  6. * @since 2021-11-05 14:31
  7. */
  8. @Service // 表明这是一个业务逻辑组件
  9. public class HelloService {
  10. }

1.4.4 使用 @Repository 注解标记的持久化层组件

  • 这个组件就是我们以前用的 Dao 类,但是以后我们整合了 Mybatis ,这里就变成了 Mapper 接口,而 Mapper 接口是由 Mybatis 和 Spring 的整合包负责扫描的。
  • 由于 Mybatis 整合包想要把 Mapper 接口背后的代理类加入 Spring 的 IOC 容器需要结合 Mybatis 对 Mapper 配置文件的解析,所以这个事情是 Mybatis 和 Spring 的整合包来完成,将来由 Mybatis 负责扫描,也不使用 @Repository 注解。
  • 当然,如果你使用 Spring Data 技术,可能需要使用该注解。

  • 示例:

  1. package com.github.fairy.era.dao;
  2. import org.springframework.stereotype.Repository;
  3. /**
  4. * @author 许大仙
  5. * @version 1.0
  6. * @since 2021-11-05 14:35
  7. */
  8. @Repository // 表明这是一个持久化层组件
  9. public class HelloDao {
  10. }

1.5 四个注解的本质

  • @Repository注解的源码:
  1. @Target({ElementType.TYPE})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Component
  5. public @interface Repository {
  6. @AliasFor(
  7. annotation = Component.class
  8. )
  9. String value() default "";
  10. }
  • 通过源码我们可以知道,@Controller 、@Service 、@Repository 这三个注解只是在 @Component 注解的基础上起了三个新的名字。
  • 对于 Spring 使用 IOC 容器管理这些组件来说,没有任何区别,但是 @Controller 、@Service 、@Repository 注解是给开发人员使用的,让我们能够很方便的分辨组件的作用。

注意:虽然它们本质上一样,但是为了代码的可读性,为了程序结构严谨我们肯定不能随便胡乱标记。

1.6 扫描

1.6.1 最基本的扫描方式

  • applicationContext.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
  6. <!-- 配置自动扫描的包 -->
  7. <context:component-scan base-package="com.github.fairy.era"></context:component-scan>
  8. </beans>
  • 测试:
  1. package com.github.fairy.era.bean;
  2. import com.github.fairy.era.component.HelloComponent;
  3. import com.github.fairy.era.controller.HelloController;
  4. import com.github.fairy.era.dao.HelloDao;
  5. import com.github.fairy.era.service.HelloService;
  6. import org.junit.Test;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.context.support.ClassPathXmlApplicationContext;
  9. /**
  10. * @author 许大仙
  11. * @version 1.0
  12. * @since 2021-11-05 11:02
  13. */
  14. public class SpringTest {
  15. @Test
  16. public void test(){
  17. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  18. HelloController helloController = context.getBean(HelloController.class);
  19. System.out.println("helloController = " + helloController);
  20. HelloService helloService = context.getBean(HelloService.class);
  21. System.out.println("helloService = " + helloService);
  22. HelloDao helloDao = context.getBean(HelloDao.class);
  23. System.out.println("helloDao = " + helloDao);
  24. HelloComponent helloComponent = context.getBean(HelloComponent.class);
  25. System.out.println("helloComponent = " + helloComponent);
  26. }
  27. }

1.6.2 指定要排除的组件

  • applicationContext.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
  6. <!-- 配置自动扫描的包 -->
  7. <context:component-scan base-package="com.github.fairy.era">
  8. <!--
  9. 指定不扫描的组件
  10. context:exclude-filter标签:指定排除规则
  11. type属性:指定根据什么来进行排除,annotation取值表示根据注解来排除
  12. expression属性:指定排除规则的表达式,对于注解来说指定全类名即可
  13. -->
  14. <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  15. </context:component-scan>
  16. </beans>
  • 测试:
  1. package com.github.fairy.era.bean;
  2. import com.github.fairy.era.component.HelloComponent;
  3. import com.github.fairy.era.controller.HelloController;
  4. import com.github.fairy.era.dao.HelloDao;
  5. import com.github.fairy.era.service.HelloService;
  6. import org.junit.Test;
  7. import org.springframework.context.ApplicationContext;
  8. import org.springframework.context.support.ClassPathXmlApplicationContext;
  9. /**
  10. * @author 许大仙
  11. * @version 1.0
  12. * @since 2021-11-05 11:02
  13. */
  14. public class SpringTest {
  15. @Test
  16. public void test(){
  17. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  18. HelloController helloController = context.getBean(HelloController.class);
  19. System.out.println("helloController = " + helloController);
  20. HelloService helloService = context.getBean(HelloService.class);
  21. System.out.println("helloService = " + helloService);
  22. HelloDao helloDao = context.getBean(HelloDao.class);
  23. System.out.println("helloDao = " + helloDao);
  24. HelloComponent helloComponent = context.getBean(HelloComponent.class);
  25. System.out.println("helloComponent = " + helloComponent);
  26. }
  27. }
  • 结果:
  1. org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.github.fairy.era.controller.HelloController' available
  2. at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351)
  3. at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
  4. at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
  5. at com.github.fairy.era.bean.SpringTest.test(SpringTest.java:22)
  6. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  7. at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  8. at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  9. at java.base/java.lang.reflect.Method.invoke(Method.java:566)
  10. at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
  11. at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  12. at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
  13. at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  14. at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
  15. at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
  16. at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
  17. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
  18. at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
  19. at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
  20. at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
  21. at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
  22. at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
  23. at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
  24. at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
  25. at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
  26. at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  27. at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
  28. at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
  29. at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
  30. at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)

1.6.3 仅扫描指定的组件

  • applicationContext.xml
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
  6. <!-- 配置自动扫描的包 -->
  7. <!-- 仅扫描指定的组件 = 关闭默认规则 + 追加规则 -->
  8. <context:component-scan base-package="com.github.fairy.era" use-default-filters="false">
  9. <!-- context:include-filter标签:指定在原有扫描规则的基础上追加的规则 -->
  10. <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
  11. </context:component-scan>
  12. </beans>
  • 测试:
  1. package com.github.fairy.era.bean;
  2. import com.github.fairy.era.controller.HelloController;
  3. import org.junit.Test;
  4. import org.springframework.context.ApplicationContext;
  5. import org.springframework.context.support.ClassPathXmlApplicationContext;
  6. /**
  7. * @author 许大仙
  8. * @version 1.0
  9. * @since 2021-11-05 11:02
  10. */
  11. public class SpringTest {
  12. @Test
  13. public void test(){
  14. ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
  15. HelloController helloController = context.getBean(HelloController.class);
  16. System.out.println("helloController = " + helloController);
  17. }
  18. }

1.7 组件的名称

  • 在使用 XML 管理 bean的时候,每个 bean 都有唯一标识(bean的id属性的值),便于在其他地方进行引用,现在使用注解以后,每个组件依然有一个唯一的标识。
  • 默认情况:类名首字母小写就是 bean 的id,比如:Student 类对应的 bean 的 id 就是 student 。
  • 当然,也可以通过注解的 value 属性改变默认的 bean 的id。
package com.github.fairy.era.service;

import org.springframework.stereotype.Service;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:31
 */
@Service("hello") // 使用value属性改变默认的bean的id
public class HelloService {

}

第二章:自动装配(⭐)

2.1 需求和目标

  • Controller 调用 Service 中的方法,Service 调用 Dao 中的方法。

自动装配.png

  • HelloDao.java
package com.github.fairy.era.dao;

import org.springframework.stereotype.Repository;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:35
 */
@Repository
public class HelloDao {

    public String getMessage() {
        return "你好,Spring";
    }
}
  • HelloService.java
package com.github.fairy.era.service;

import com.github.fairy.era.dao.HelloDao;
import org.springframework.stereotype.Service;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:31
 */
@Service
public class HelloService {

    private HelloDao helloDao;

    public String getMessage(){
        return  helloDao.getMessage();
    }
}
  • HelloController.java
package com.github.fairy.era.controller;

import com.github.fairy.era.service.HelloService;
import org.springframework.stereotype.Controller;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:28
 */
@Controller
public class HelloController {

    private HelloService helloService;

    public String getMessage() {
        return helloService.getMessage();
    }
}

2.2 前提

  • 参与自动装配的组件都必须在 IOC 容器中。

2.3 @Autowired 注解

  • 在成员变量上直接标记 @Autowired 注解即可,不需要提供 setXxx() 方法,以后我们在项目中的正式用法就是这样。

  • 示例:

package com.github.fairy.era.service;

import com.github.fairy.era.dao.HelloDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:31
 */
@Service
public class HelloService {

    // 给Service装配Dao
    @Autowired
    private HelloDao helloDao;

    public String getMessage(){
        return  helloDao.getMessage();
    }
}
package com.github.fairy.era.controller;

import com.github.fairy.era.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:28
 */
@Controller
public class HelloController {

    // 给Controller装配Service
    @Autowired
    private HelloService helloService;

    public String getMessage() {
        return helloService.getMessage();
    }
}

2.4 @Autowired 注解的细节

  • @Autowired 注解源码:
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
    boolean required() default true;
}
  • @Autowired 可以标记在构造器、方法、参数、属性、以及作为元注解使用。

  • 示例:

package com.github.fairy.era.controller;

import com.github.fairy.era.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:28
 */
@Controller
public class HelloController {

    private final HelloService helloService;

    @Autowired
    public HelloController(HelloService helloService) {
        this.helloService = helloService;
    }

    public String getMessage() {
        return helloService.getMessage();
    }
}

2.5 @Autowired 注解的工作流程

@Autowired注解的工作流程.png

  • 首先根据所需要的组件类型到 IOC 容器中查找

    • 能够找到唯一的 bean:直接执行装配
    • 如果完全找不到匹配这个类型的 bean:装配失败
    • 和所需类型匹配的 bean 不止一个
      • 没有 @Qualifier 注解:根据 @Autowired 标记位置成员变量的变量名作为 bean 的 id 进行匹配
        • 能够找到:执行装配
        • 找不到:装配失败
      • 使用 @Qualifier 注解:根据 @Qualifier 注解中指定的名称作为 bean 的id进行匹配
        • 能够找到:执行装配
        • 找不到:装配失败
  • 示例:

package com.github.fairy.era.dao;

import org.springframework.stereotype.Repository;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:35
 */
@Repository
public class HelloDao {

    public String getMessage() {
        return "你好,Spring";
    }
}
package com.github.fairy.era.service;

import com.github.fairy.era.dao.HelloDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:31
 */
@Service("helloService2")
public class HelloService {

    @Autowired
    private HelloDao helloDao;

    public String getMessage(){
        return  helloDao.getMessage();
    }
}
package com.github.fairy.era.controller;

import com.github.fairy.era.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:28
 */
@Controller
public class HelloController {

    @Autowired
    @Qualifier("helloService2")
    private HelloService helloService;

    public String getMessage() {
        return helloService.getMessage();
    }
}

2.6 佛系装配

  • 给 @Autowired 注解设置 required = false 属性表示:能装就装,装不上就不装。但是实际开发时,基本上所有需要装配组件的地方都是必须装配的,用不上这个属性。

注意:如果类中同时存在装配属性的 setXxx() 方法会使 required = false 设定失效。

  • 示例:
package com.github.fairy.era.controller;

import com.github.fairy.era.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:28
 */
@Controller
public class HelloController {

    // 给@Autowired注解设置required = false属性表示:能装就装,装不上就不装
    @Autowired(required = false)
    private HelloService helloService;

    public String getMessage() {
        return helloService.getMessage();
    }
}

第三章:完全注解开发

3.1 创建配置类

  • SpringApplication.java
package com.github.fairy.era;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 15:20
 */
@ComponentScan(basePackages = "com.github.fairy.era") // 相当于<context:component-scan></context:component-scan>
@Configuration // 相当于配置文件
public class SpringApplication {

}

3.2 组件类

  • Person.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 15:23
 */
public class Person {

    private String name;

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
  • HelloDao.java
package com.github.fairy.era.dao;

import org.springframework.stereotype.Repository;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:35
 */
@Repository
public class HelloDao {

    public String getMessage() {
        return "你好,Spring";
    }
}
  • HelloService.java
package com.github.fairy.era.service;

import com.github.fairy.era.dao.HelloDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:31
 */
@Service
public class HelloService {

    @Autowired
    private HelloDao helloDao;

    public String getMessage(){
        return  helloDao.getMessage();
    }
}
  • HelloController.java
package com.github.fairy.era.controller;

import com.github.fairy.era.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 14:28
 */
@Controller
public class HelloController {

    // 给@Autowired注解设置required = false属性表示:能装就装,装不上就不装
    @Autowired(required = false)
    private HelloService helloService;

    public String getMessage() {
        return helloService.getMessage();
    }
}

3.3 在配置类中配置 Bean

  • SpringApplication.java
package com.github.fairy.era;

import com.github.fairy.era.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 15:20
 */
@ComponentScan(basePackages = "com.github.fairy.era") // 相当于<context:component-scan></context:component-scan>
@Configuration // 相当于配置文件
public class SpringApplication {

    @Bean // 相当于bean标签
    public Person person(){
        Person person = new Person();
        person.setName("许大仙");
        return person;
    }

}

3.4 测试

package com.github.fairy.era.bean;

import com.github.fairy.era.SpringApplication;
import com.github.fairy.era.controller.HelloController;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
public class SpringTest {

    @Test
    public void test(){
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringApplication.class);

        HelloController helloController = context.getBean(HelloController.class);

        String message = helloController.getMessage();

        System.out.println("message = " + message);

        Person person = context.getBean(Person.class);

        System.out.println("person = " + person);
    }
}

第四章:整合 Junit4

4.1 概述

  • Spring 整合 Junit 有如下的好处:
  • ① 不需要自己创建 IOC 容器对象了。
  • ② 任何需要的 bean 都可以在测试类中直接享受自动装配。

4.2 导入依赖

  • pom.xml
<!-- Spring -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.12</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.12</version>
</dependency>
<!-- junit单元测试 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

4.3 组件类

  • Person.java
package com.github.fairy.era.bean;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 15:23
 */
public class Person {

    private String name;

    public String getName() {
        return name;
    }

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

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

4.4 配置类

  • SpringApplication.java
package com.github.fairy.era;

import com.github.fairy.era.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 15:20
 */
@ComponentScan(basePackages = "com.github.fairy.era") // 相当于<context:component-scan></context:component-scan>
@Configuration // 相当于配置文件
public class SpringApplication {

    @Bean // 相当于bean标签
    public Person person(){
        Person person = new Person();
        person.setName("许大仙");
        return person;
    }

}

4.5 测试

package com.github.fairy.era.bean;

import com.github.fairy.era.SpringApplication;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 许大仙
 * @version 1.0
 * @since 2021-11-05 11:02
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = SpringApplication.class)
public class SpringTest {

    @Autowired
    private Person person;

    @Test
    public void test(){
        System.out.println("person = " + person);
    }
}