目录
Spring框架的作用
通过Spring创建并管理对象
--组件扫描
--@Bean方法
如何选择创建并管理对象的方式
自动装配
关于Spring框架的异常
NoSuchBeanDefinitionException
测试1
测试2
Spring框架的作用
- 主要解决了创建对象和管理对象的问题.
- 在使用Spring框架后,当需要某个对象时,直接通过Spring获取此对象即可.
- Spring可以保证类的对象的唯一性,使得各组件出现依赖关系时,不会创建多个相同的对象.
- 由于Spring会创建很多个对象并管理起来,开发者需要时直接获取即可,所以,Spring也通常被称为"Spring容器".
通过Spring创建并管理对象
--组件扫描
--组件扫描
Spring提供了组件扫描的机制,它可以扫描指定的包,并查找此包及其子孙包下是否存在组件类,判定组件类的标志是类上是否存在组件注解.
基础的组件注解有:
@Component @Controller @Service @Repository
在Spring框架的解释中,以上4个注解是完全等效的,只是语义不同.
所以,当某个类需要被Spring框架创建对象时,需要:
- 确保这个类在组件扫描的范围之内
- 确保这个类添加了组件注解
(在Spring Boot项目中,默认就已经配置好了组件扫描,扫描的根包就是创建项目时已经存在的包.)
--@Bean方法
在Spring框架的使用中,如果某个类添加了`@Configuration`注解,则此类将是“配置类”。
注意:配置类也必须在组件扫描的范围内。
在配置类中,可以自行添加一些方法,在方法上添加`@Bean`注解,则此方法会被Spring自动调用,且方法返回的对象也会被Spring管理。
在同一个配置类中,允许存在多个`@Bean`方法。
关于方法的声明:
- 访问权限:应该是`public`
- 返回值类型:你希望Spring管理的对象的类型
- 方法体:应该正确的返回与声明匹配的对象
- 方法名称:自定义
所以,当某个类需要被Spring框架管理对象时,需要:
- 在配置类中添加`@Bean`方法,使用此方法返回需要被管理的对象
如何选择创建并管理对象的方式
仅自定义的类型可以使用组件扫描的方式,当然,自定义的类型也可以使用`@Bean`方法的做法,但是不推荐。
非自定义的类型不可以使用组件扫描的方式(因为你没有办法在这些类型上添加组件注解),只能使用`@Bean`方法的做法。
自动装配
当某个属性需要值时,或被Spring调用的方法需要参数值时,Spring框架会自动从容器中查找符合的对象,自动为属性或方法的参数赋值。
仅自定义的类型可以使用组件扫描的方式,当然,自定义的类型也可以使用`@Bean`方法的做法,但是不推荐。
非自定义的类型不可以使用组件扫描的方式(因为你没有办法在这些类型上添加组件注解),只能使用`@Bean`方法的做法。
自动装配
当某个属性需要值时,或被Spring调用的方法需要参数值时,Spring框架会自动从容器中查找符合的对象,自动为属性或方法的参数赋值。
关于Spring框架的异常
NoSuchBeanDefinitionException
*无此Bean的异常**
在异常信息中会提示到底是缺少哪个Bean,例如以下提示的`cn.tedu.csmall.server.controller.CategoryController`,然后,再结合你的配置来检查!
创建对象的方式只有2种,要么是组件扫描,要么是`@Bean`方法,检查对应的代码即可。
如果提示的类型并不是自已配置的,且应该是正常的可用的,可考虑为依赖项错误的问题,则参考《前置技术清单中第3条来解决》。
```
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'cn.tedu.csmall.server.controller.CategoryController' available
```
MVC = Model(数据模型)+ View(视图)+ Controller(控制器)
测试1
假设在项目中存在:
- `IBrandRepository`
- `BrandRepositoryImpl`
- `IBrandService`
- `BrandServiceImpl`
- `BrandController`
其依赖关系是:在`Service`组件中需要使用到`Repository`,在`Controller`组件中需要使用到`Service`。
要实现以上目标,需要:
- 以上各类和接口都应该在组件扫描的根包或其子孙包下
- `IBrandRepository`、`IBrandService`不需要添加注解,而`BrandRepositoryImpl`应该添加`@Repository`注解,`BrandServiceImpl`添加`@Service`注解,`BrandController`添加`@Controller`注解
- 在`BrandServiceImpl`中声明`BrandRepositoryImpl`类型的变量(暂时声明为`public`)
- 【测试】在没有添加`@Autowired`之前,此变量的值为`null`
- 可以在测试类中自动装配`BrandServiceImpl`,并在测试方法中输出`BrandRepositoryImpl`变量的值,例如:
@Autowired
BrandServiceImpl brandService;
@Test
public void testBrandAutowired() {
System.out.println(brandService.brandRepositoryImpl);
}
- 【测试】当已经添加`@Autowired`之后,此变量的值为`BrandRepositoryImpl`类型的对象
- 使得`BrandRepositoryImpl`实现`IBrandRepository`接口
- 【测试】将`BrandServiceImpl`中,原本声明为`BrandRepositoryImpl`类型的变量,改为`IBrandRepository`类型,再次观察,此变量的值不变
- 在`BrandController`中声明`BrandServiceImpl`类型的变量
- 【测试】在没有添加`@Autowired`之前,此变量的值为`null`
- 【测试】当已经添加`@Autowired`之后,此变量的值为`BrandServiceImpl`类型的对象
- 使得`BrandServiceImpl`实现`IBrandService`接口
- 【测试】将`BrandController`中,原本声明为`BrandServiceImpl`类型的变量,改为`IBrandService`类型,再次观察,此变量的值不变
测试2
假设在项目中存在:
- `IAlbumRepository`
- `AlbumRepositoryImpl`
- `IAlbumService`
- `AlbumServiceImpl`
- `AlbumController`
其依赖关系是:在`Service`组件中需要使用到`Repository`,在`Controller`组件中需要使用到`Service`。
案例目标:
- Spring能自动创建`AlbumRepositoryImpl`类的对象
- 在`repo.impl`包下创建此类,并且,在此类上添加`@Repository`
- 检验方式:添加构造方法并输出;在测试类中,自动装配此类型的对象,并输出
- Spring能自动创建`AlbumServiceImpl`类的对象
- 同上,此类应该在`service.impl`包下(`impl`包不存在,需创建)
- 在`AlbumServiceImpl`类有`AlbumRepositoryImpl`的属性,并自动装配
- 在`AlbumServiceImpl`内部,声明`AlbumRepositoryImpl`类型的变量,并添加`@Autowired`注解
- 检查方式:在测试类中,输出`AlbumServiceImpl`对象的`AlbumRepositoryImpl`属性,应该是有值的
*无此Bean的异常** 在异常信息中会提示到底是缺少哪个Bean,例如以下提示的`cn.tedu.csmall.server.controller.CategoryController`,然后,再结合你的配置来检查! 创建对象的方式只有2种,要么是组件扫描,要么是`@Bean`方法,检查对应的代码即可。 如果提示的类型并不是自已配置的,且应该是正常的可用的,可考虑为依赖项错误的问题,则参考《前置技术清单中第3条来解决》。
``` org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'cn.tedu.csmall.server.controller.CategoryController' available ```
MVC = Model(数据模型)+ View(视图)+ Controller(控制器)
测试1
假设在项目中存在:
- `IBrandRepository`
- `BrandRepositoryImpl`
- `IBrandService`
- `BrandServiceImpl`
- `BrandController`
其依赖关系是:在`Service`组件中需要使用到`Repository`,在`Controller`组件中需要使用到`Service`。
要实现以上目标,需要:
- 以上各类和接口都应该在组件扫描的根包或其子孙包下
- `IBrandRepository`、`IBrandService`不需要添加注解,而`BrandRepositoryImpl`应该添加`@Repository`注解,`BrandServiceImpl`添加`@Service`注解,`BrandController`添加`@Controller`注解
- 在`BrandServiceImpl`中声明`BrandRepositoryImpl`类型的变量(暂时声明为`public`)
- 【测试】在没有添加`@Autowired`之前,此变量的值为`null`
- 可以在测试类中自动装配`BrandServiceImpl`,并在测试方法中输出`BrandRepositoryImpl`变量的值,例如:
@Autowired
BrandServiceImpl brandService;
@Test
public void testBrandAutowired() {
System.out.println(brandService.brandRepositoryImpl);
}
- 【测试】当已经添加`@Autowired`之后,此变量的值为`BrandRepositoryImpl`类型的对象
- 使得`BrandRepositoryImpl`实现`IBrandRepository`接口
- 【测试】将`BrandServiceImpl`中,原本声明为`BrandRepositoryImpl`类型的变量,改为`IBrandRepository`类型,再次观察,此变量的值不变
- 在`BrandController`中声明`BrandServiceImpl`类型的变量
- 【测试】在没有添加`@Autowired`之前,此变量的值为`null`
- 【测试】当已经添加`@Autowired`之后,此变量的值为`BrandServiceImpl`类型的对象
- 使得`BrandServiceImpl`实现`IBrandService`接口
- 【测试】将`BrandController`中,原本声明为`BrandServiceImpl`类型的变量,改为`IBrandService`类型,再次观察,此变量的值不变
测试2
假设在项目中存在:
- `IAlbumRepository`
- `AlbumRepositoryImpl`
- `IAlbumService`
- `AlbumServiceImpl`
- `AlbumController`
其依赖关系是:在`Service`组件中需要使用到`Repository`,在`Controller`组件中需要使用到`Service`。
案例目标:
- Spring能自动创建`AlbumRepositoryImpl`类的对象
- 在`repo.impl`包下创建此类,并且,在此类上添加`@Repository`
- 检验方式:添加构造方法并输出;在测试类中,自动装配此类型的对象,并输出
- Spring能自动创建`AlbumServiceImpl`类的对象
- 同上,此类应该在`service.impl`包下(`impl`包不存在,需创建)
- 在`AlbumServiceImpl`类有`AlbumRepositoryImpl`的属性,并自动装配
- 在`AlbumServiceImpl`内部,声明`AlbumRepositoryImpl`类型的变量,并添加`@Autowired`注解
- 检查方式:在测试类中,输出`AlbumServiceImpl`对象的`AlbumRepositoryImpl`属性,应该是有值的
假设在项目中存在: - `IAlbumRepository` - `AlbumRepositoryImpl` - `IAlbumService` - `AlbumServiceImpl` - `AlbumController` 其依赖关系是:在`Service`组件中需要使用到`Repository`,在`Controller`组件中需要使用到`Service`。 案例目标: - Spring能自动创建`AlbumRepositoryImpl`类的对象 - 在`repo.impl`包下创建此类,并且,在此类上添加`@Repository` - 检验方式:添加构造方法并输出;在测试类中,自动装配此类型的对象,并输出 - Spring能自动创建`AlbumServiceImpl`类的对象 - 同上,此类应该在`service.impl`包下(`impl`包不存在,需创建) - 在`AlbumServiceImpl`类有`AlbumRepositoryImpl`的属性,并自动装配 - 在`AlbumServiceImpl`内部,声明`AlbumRepositoryImpl`类型的变量,并添加`@Autowired`注解 - 检查方式:在测试类中,输出`AlbumServiceImpl`对象的`AlbumRepositoryImpl`属性,应该是有值的



