五、环境扫描路径

虽然我们没有告诉Spring扫描路径是什么,但是有一些注解已经告诉Spring扫描路径是什么了

如启动类注解@SpringBootApplication。

里面有一个注解是@componentScan这个注解就是扫描路径注解。

指定扫描路径

六、依赖注入(DI)详解

依赖注入是⼀个过程,是指IoC容器在创建Bean时,去提供运行时所依赖的资源,而资源指的就是对象. 在下面程序案例中

我们使用了 @Autowired 这个注解,完成了依赖注⼊的操作. 简单来说,就是把对象取出来放到某个类的属性中.。在一些文章中。依赖注⼊也被称之为"对象注入","属性装配",

具体含义需要结合文章的上下文来理解

关于依赖注入,Spring也给我们提供了三种方式:

6.1 @Autowired属性注入(Field-Injection)

这个方法我们在上一篇文章使用过。这是重述一遍

@RestController
@RequestMapping("/book")
public class BookController {
//属性注入
    @Autowired
    private BookService bookService;
}

 

6.2 构造方法注入(Constructor-Injection)

注:当我们手动加上构造函数之后。一定要养成习惯把默认无参构造方法写上

当有单个构造函数

Spring知道使用哪个。因此会正常运行。

  
@RestController
@RequestMapping("/book")
public class BookController {
//构造方法注入
      private BookService bookService;
      public BookController(BookService bookService){
          this.bookService = bookService;
    }
@Controller("bean") //创建对象  //括号中是对bean进行重命名 如果没有指定名称spring帮我们指定
public class UserController {
    private UserService userService;
    private UserRepository userRepository;

    public UserController(UserService userService, UserRepository userRepository) {
        this.userService = userService;
        this.userRepository = userRepository;
    }
    public void say(){
        userService.say();
        userRepository.say();
        System.out.println("Hi Controller!!!");
    }
}

《JavaEE进阶》----12.<SpringIOC&DI【扫描路径+DI详解+经典面试题+总结】>-LMLPHP 

当有多个构造函数

@Controller("bean") //创建对象  //括号中是对bean进行重命名 如果没有指定名称spring帮我们指定
public class UserController {
    private UserService userService;
    private UserRepository userRepository;
    
    public UserController(){
        
    }

    public UserController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public UserController(UserService userService, UserRepository userRepository) {
        this.userService = userService;
        this.userRepository = userRepository;
    }
    public void say(){
        userService.say();
        userRepository.say();
        System.out.println("Hi Controller!!!");
    }
}

 优先使用默认无参构造函数。如果没有。就会报错。

《JavaEE进阶》----12.<SpringIOC&DI【扫描路径+DI详解+经典面试题+总结】>-LMLPHP @Autowired 指定使用某个构造函数:

    @Autowired
    public UserController(UserService userService, UserRepository userRepository) {
        this.userService = userService;
        this.userRepository = userRepository;
    }

《JavaEE进阶》----12.<SpringIOC&DI【扫描路径+DI详解+经典面试题+总结】>-LMLPHP 

6.3 Setter 注入(SetterInjection)

 也需要搭配@AutoWired注解才可以正常注入。

private UserService userService;
private UserRepository userRepository;
@Autowired
public void setUserService(UserService userService) {
    this.userService = userService;
}
@Autowired
public void setUserRepository(UserRepository userRepository) {
    this.userRepository = userRepository;
}

《JavaEE进阶》----12.<SpringIOC&DI【扫描路径+DI详解+经典面试题+总结】>-LMLPHP

6.3三种依赖注入优缺点

属性注入(Spring最不推荐,但没关系):

构造方法注入(Spring4.x推荐):

我们可以点进@Autowired注解。再点击目录。看到我们现在使用的Spring版本。

《JavaEE进阶》----12.<SpringIOC&DI【扫描路径+DI详解+经典面试题+总结】>-LMLPHP

Setter注入(Spring3.x推荐)

6.4@AutoWired存在的问题

当同一类型存在多个Bean时。使用@Autowired会存在问题

@Configuration
public class BeanConfig {
    @Bean
    public UserInfo userInfo1(){
        UserInfo userInfo = new UserInfo();
        userInfo.setId(120);
        userInfo.setName("张三");
        userInfo.setAge(18);
        return userInfo;
    }

    @Bean
    public UserInfo userInfo2(){
        UserInfo userInfo2 = new UserInfo();
        userInfo2.setId(121);
        userInfo2.setName("李四");
        userInfo2.setAge(28);
        return userInfo2;
    }
}

《JavaEE进阶》----12.<SpringIOC&DI【扫描路径+DI详解+经典面试题+总结】>-LMLPHP

报错的原因是非唯一Bean对象。

Spring提供了一下几种解决方案。

@Primary

在构造多个对象时

使用@Primary注解:当存在多个相同类型的Bean注入时,加上@Primary注解,来确定默认的实现。

@Configuration
public class BeanConfig {
    @Primary
    @Bean
    public UserInfo userInfo1(){
        UserInfo userInfo = new UserInfo();
        userInfo.setId(120);
        userInfo.setName("张三");
        userInfo.setAge(18);
        return userInfo;
    }

    @Bean
    public UserInfo userInfo2(){
        UserInfo userInfo2 = new UserInfo();
        userInfo2.setId(121);
        userInfo2.setName("李四");
        userInfo2.setAge(28);
        return userInfo2;
    }
}

@Qualifier

使用@Qualifier注解:在注入时。指定当前要注入的bean对象。在@Qualifier的value属性中,指定注入的bean 的名称。

@Qualifier注解不能单独使用,必须配合@Autowired使用

    @Qualifier("userInfo2")//指定bean的名称
    @Autowired
    private UserInfo userInfo;


    public void say(){
        System.out.println("Hi Controller!!!");
        userService.say();
        System.out.println(userInfo);
    }

@Resource

使用@Resource注解:是按照bean的名称进行注入。通过name属性指定要注入的bean的名称。

不用@Autowirede注解配合使用。

    @Resource(name="userInfo2")
    private UserInfo userInfo;


    public void say(){
        System.out.println("Hi Controller!!!");
        userService.say();
        System.out.println(userInfo);
    }

常见面试题:

1.@Autowird与@Resource的区别

2.Spring,SpringBoot,SpringMVC之间的区别和联系,你是如何理解的?

3.ApplicationContext VS BeanFactory

4.三种依赖注入优缺点

属性注入(Spring最不推荐,但没关系):

构造方法注入(Spring4.x推荐):

我们可以点进@Autowired注解。再点击目录。看到我们现在使用的Spring版本。

《JavaEE进阶》----12.<SpringIOC&DI【扫描路径+DI详解+经典面试题+总结】>-LMLPHP

Setter注入(Spring3.x推荐)

5.常见注解有哪些?分别是什么作用?

1. web url映射: @RequestMapping

2.参数接收和接口响应:@RequestParam,@RequestBody,@ResponseBody

3.bean的存储:@Controller,@Service,@Repository,@Component,@Configuration,@Bean

4.bean的获取: @Autowired, @Qualifier, @Resource

5.多个bean的默认指定:@Primary

6.Spring两大核心思想IOC和AOP


总结:

告诉spring管理Bean,Bean的存储

1.类注解:五大注解@Controller@Component@Configuration@Service@Repository

2.方法注解:@Bean

Bean的名称:

1.五大注解

类名首字母小写,如果前两位字母均为大写,则为原类名,也可以指定Bean的名称

指定方法:@Controller(“beanName”)

2.@bean

默认名称是方法名,也可以指定名称:@Bean(“beanName”)

使用场景

1.五大注解 自己开发的程序

2.@Bean

①存储第三方的对象(代码不在自己的项目中)

②一个类型需要创建多个对象时

获取bean三种扫描路径的方式

通过Spring运行环境的Spring上下文 

ApplicationContext context = SpringApplication.run(IocDomeApplication.class, args);

获取Bean的功能是BeanFeactory提供的 

三种方式

1.通过类型

UserController bean1 = context.getBean(UserController.class);
bean1.say();

2.通过bean名称

UserService userService =(UserService) context.getBean("userService");
userService.say();

3.通过bean名称+类型

UserComponent userComponent = context.getBean("userComponent", UserComponent.class);
userComponent.say();

扫描路径:

默认扫描路径:启动类所在的路径

指定扫描路径: 在启动类上面加上如下注解

@ComponentScan(“扫描路径”)
09-08 19:44