五、环境扫描路径
虽然我们没有告诉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!!!");
}
}
当有多个构造函数
@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!!!");
}
}
优先使用默认无参构造函数。如果没有。就会报错。
@Autowired 指定使用某个构造函数:
@Autowired
public UserController(UserService userService, UserRepository userRepository) {
this.userService = userService;
this.userRepository = userRepository;
}
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;
}
6.3三种依赖注入优缺点
属性注入(Spring最不推荐,但没关系):
构造方法注入(Spring4.x推荐):
我们可以点进@Autowired注解。再点击目录。看到我们现在使用的Spring版本。
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;
}
}
报错的原因是非唯一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版本。
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(“扫描路径”)