1.前言
我们知道物件都会随着时代的发展,越变越简单的。Spring 框架也不意外;我们在之前存储Bean对象是在配置文件中添加<bean></bean>来存入Bean对象到Spring当中的,使用那个类对象就要存入那个,一个两个类对象还好,如果需要的对象多了,就会非常麻烦。现在,随着 Spring 发展不用再担心这个了,我们可以通过配置轻松解决这件事。往下看,看看怎么个事吧!
2.存储 Bean对象
2.1 前置任务:配置扫描路径(重中之重)
在spring-config.xml
文件中完成配置,这些代码不用记,随用随取就行了,我把它放在下面了,如果有需要来这里找就行了,配置代码如下:
<?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:content="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 https://www.springframework.org/schema/context/spring-context.xsd"> <content:component-scan base-package="com.demo"></content:component-scan> </beans>
注意:想要将对象成功的存储到 Spring 中,我们需要配置⼀下存储对象的扫描包路径(base-package=""这个选项),只有被配置的包下的所有类,添加了注解才能被正确的识别并保存到 Spring 中。
2.2 添加注解存储 Bean 对象
将对象存储到 Spring 中,有两种注解类型可以实现:
- 1.类注解:@Controller、@Service、@Repository、@Component、@Configuration
- 2.方法注解:@Bean
2.2.1 类注解
在类注解中虽然它们的五个名字各不相同,但是他们的作用都是一样的,一会解释为啥这样设计;并且这里面@Component
是其他四个类注解的父类。
注:它们五个作用是一样,这里举例就用五个类注解其中一个来举例了,这里使用@Controller
。如果想验证它们是否作用一样,可以将例子代码的@Controller
换成其他类注解验证。
例子:
将 Bean对象 存储到 Spring 的代码:
@Controller //将对象存储到 Spring 中 public class UserController { public void sayHi() { System.out.println("唱跳rap"); } }
我们可以在启动项中验证一下是否放入成功,如何验证呢?那就是我们在 Spring 中去取存入的对象看能不能取出来就行了。代码如下:
public class App { public static void main(String[] args) { //1.加载 Spring 上下文 ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml"); //2.取对象 UserController userController = context.getBean("userController", UserController.class); //3.使用 Bean对象 userController.sayHi(); } }
看控制台非常成功的完成了唱跳rap,这样证明我们完成使用@Controller
将 Bean对象存储到了Spring当中了:
✨五大类注解作用一样,为啥不合并?
既然功能一样,为啥需要那么多的类注解呢?
这里举一个特别好理解的例子,我们知道咱国家的车牌号组成是 城市名称缩写+ 字母+编号 ,就像我们开封的就是 豫 B: ×××××× ,我们首都就是 京:×××××× 。我们看车票号就能看出来它是哪里的。五大类注解也是这样,有五大类注解,我们看到那个注解就知道这个注解是使用在那个范围的!
这里说到了五大类注解使用范围不一样,那就看看它们使用范围:
五大类注解用途:
1.@Controller(控制器):归属于业务逻辑层,用来控制用户的行为,它用来检查用户参数的有效性。
2.@Service(服务):归属于服务层,调用持久化类实现相应的功能。【不直接和数据库交互的,它类似于控制中心】
3.@Repository(仓库):归属于持久层,是直接和数据库进行交互的。通常每一个表都会对应一个@Repository
4.@Configuration(配置):归属于配置层,是用来配置当前项目的一些信息。
5.@Component(组件):归属于公共工具类,提供某些公共方法。
五大类分工不同,那它们是如何串联起来工作的呢?看下方:
2.2.2 方法注解 @Bean
类注解是添加到某个类上的,而方法注解是放到某个⽅法上的,只使用 @Bean
是不能完成对象的存储的,需要配合五大类注解使用才能存储成功,使用方法如下:
存储对象过程:
@Component public class UserBeans { @Bean public User user1() { //这里是伪代码 User user =new User(); user.setId(1); user.setName("张三"); return user; } }
这里注意,@Bean
存储的是方法的返回值,比如上面这个方法,它存入就是方法中new
的 user
这个实例对象。
在使用@Bean
时,可以通过设置 name 属性给 Bean 对象进⾏重命名操作,如下代码:
@Component public class UserBeans { @Bean(name = {"u1","u2"}) public User user1() { //这里是伪代码 User user =new User(); user.setId(1); user.setName("张三"); return user; } }
可以看出这个name属性是个数组,因此我们可以给这个方法其很多个别名;这里起是别名,因此使用原来的名字user1
也是可以取到这个对象的,也就是说,现在这个对象有三个名字分别是u1
、u2
、user1
。
3.获取 Bean对象
获取 bean 对象也叫做对象装配(对象注入),是把对象取出来放到某个类中,就是我们原原来写的成员变量,我们可以给他赋值,现在只是将赋值的这个过程给到 Spring 了。
对象装配(对象注入)的实现方法有三种:
- 1.属性注入
- 2.构造方法注入
- 3.Setter注入
下面我们通过三种不同的实现方法,将Service类注入到Controller类中。
这里需要有前置工作,就是将Service类先存入到 Spring 当中,代码如下:
@Service public class UserService { public User getUser(int id) { // 伪代码,不连接数据库 User user = new User(); user.setId(id); user.setName("Java-" + id); return user; } }
3.1 属性注入
注入代码如下:
public class UserController { //属性注入 @Autowired private UserService userService; public User getUser(int id) { return userService.getUser(id); } }
3.2 构造方法注入
注入代码如下:
@Controller public class UserController { private UserService userService; @Autowired public UserController(UserService userService) { this.userService = userService; } public User getUser(int id) { return userService.getUser(id); } }
注意:如果只有⼀个构造⽅法,那么 @Autowired
注解可以省略;但是如果类中有多个构造⽅法,那么需要添加上 @Autowired
来明确指定到底使⽤哪个构造⽅法,否则程序会报错.
3.3 Setter 注⼊
Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired
注解
@Controller public class UserController { private UserService userService; @Autowired public void setUserService(UserService userService) { this.userService = userService; } public User getUser(int id) { return userService.getUser(id); } }
3.4 三种注释的优缺点
属性注⼊的优点是简洁,使⽤⽅便;缺点是只能⽤于 IoC 容器,如果是非 IoC 容器不可⽤,并且只有在使⽤的时候才会出现空指针异常
构造⽅法注⼊是 Spring 推荐的注入方式,缺点是如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,它的优点是通⽤性,在使⽤之前⼀定能把保证注⼊的类不为空。
Setter ⽅式是 Spring 前期版本推荐的注入方式,但通⽤性不如构造方法,所有 Spring 现版本已经推荐使⽤构造⽅法注⼊的⽅式来进⾏类注⼊了
3.5 另⼀种注⼊关键字:@Resource
在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊。
🎉 @Autowired 和 @Resource 的区别
1.出身不同:@Autowired 来⾃于 Spring,而 @Resource 来⾃于 JDK 的注解;
2.使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如:name 设置,根据名称获取 Bean。
3.@Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,而@Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊