发布时间:2023-01-09 22:00
目录
一、引言
二、存储Bean对象
2.1 准备工作
2.2 添加注解存储Bean对象
2.2.1 @Controller(控制器存储)
2.2.2 @Service(服务存储)
2.2.3 @Repository(仓库存储)
2.2.4 @Component(组件存储)
2.2.5 @Configuration(配置存储)
2.3 为什么需要这么多类注解
2.4 五大类注解的关系
2.5 Bean的命名
2.6 方法注解@Bean
三、获取Bean对象
3.1 使用@Autowired
3.1.1 使用属性注入的方式获得对象
3.1.2 使用构造方法进行注入
3.1.3 setter注入
3.1.4 三种方法的比较
3.2 @Resource注入
3.3 @Resource和@Autowired区别
3.4 一个对象类型被Spring注入多个的解决方案
3.4.1 @Resource(name="")
3.4.2 @Autowired+@Qualifier
四、总结
在上篇博客中,我们可以实现Spring读取和存储对象的方法。但是在操作的过程中,我们需要在spring.xml当中添加一行bean的注册内容才行,如下图所示:
我们可以发现,才用这种方式存储或者读取对象并没有想象中那么简单。
在Spring中,要想更简单的存储和读取对象的核心是使用注解。接下来将会介绍如何使用Spring的相关注解来存储和读取对象。
要想将对象成功的存储到Spring中,需要配置一下存储对象的扫描包路径,只有配置的包下的所有类,加了注解之后才能被正确的识别并保存到Spring中。
base-package的属性就是组建的扫描路径。
类注解:@controller @Service @Repository @Component@Configuration
方法注解:@Bean
使用@Controller存储bean的代码:
package service;
import org.springframework.stereotype.Controller;
@Controller //这个注解的作用,告诉Spring在启动的时候将当前对象存储到容器中,相当于
public class UserController {
public void sayhello(){
System.out.println("hello control");
}
}
获取bean的代码:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserController;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = applicationContext.getBean("userController", UserController.class);
userController.sayhello();
}
}
getBean方法中的第一个参数是bean的ID,一般情况下,使用注解bean的id为类名首字母小写。
使用@Service存储bean的代码:
package service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
public void sayhello(){
System.out.println("hello service");
}
}
获取bean的代码:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
UserService userService= applicationContext.getBean("userService", UserService.class);
userService.sayhello();
}
}
使用@Repository存储bean的代码:
package service;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
public void sayhello(){
System.out.println("hello repository");
}
}
获取bean的代码:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserRepository;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
UserRepository userRepository = applicationContext.getBean("userRepository",UserRepository.class);
userRepository.sayhello();
}
}
使用@Component存储bean的代码:
package service;
import org.springframework.stereotype.Component;
@Component
public class UserComponent {
public void sayhello(){
System.out.println("hello component");
}
}
获取bean的代码:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserComponent;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
UserComponent userComponent= applicationContext.getBean("userComponent",UserComponent.class);
userComponent.sayhello();
}
}
使用@Configuration存储bean的代码:
package service;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserConfiguration {
public void sayhello(){
System.out.println("hello configuration");
}
}
获取bean的代码:
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserConfiguration;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
UserConfiguration userConfiguration= applicationContext.getBean("userConfiguration", UserConfiguration.class);
userConfiguration.sayhello();
}
}
不同的类注解,用途不同。
@Controller :业务逻辑层。验证前端参数是否合法。
@Service:服务层。数据的组装和调用数据库接口的管理。
@Repository:数据持久层。数据库的查询和管理。
@Configuration:配置层。设置当前项目中所有配置信息。
@Component:实体类。
看 @Controller 、@Service 、 @Repository 、 @Configuration 等注解的源码,可以发现这些注解都是@Component 的“⼦类”。
使用标准的大驼峰命名:读取的时候⾸字⺟小写就可以获取到 bean 了。
如果是前两个字母都是大写:读取的时候就不用变,直接用。
package service;
import org.springframework.context.annotation.Configuration;
@Configuration
public class USer {
public void sayhello(){
System.out.println("hello USer");
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.USer;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
USer uSer= applicationContext.getBean("USer", USer.class);
uSer.sayhello();
}
}
将当前方法返回的对象存入到Spring。
注意:
①@Bean必须配合类注解一起使用。原因:出于对性能的考量。因为扫描所有方法的返回值是否需要将其存储在Spring中,代价很会很大。因此,只扫描类注解+@Bean来实现对象的托管。
package service;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserBean {
@Bean
public UserInform getUser(){
UserInform userInform = new UserInform();
userInform.setId(1);
userInform.setName("小明");
return userInform;
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserInform;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
UserInform userInform = applicationContext.getBean("getUser", UserInform.class);
System.out.println(userInform);
}
}
②@Bean重命名
可以给当前对象指定多个名称,使用多个名称获取的对象都是同一个
@Bean重命名后使用原方法名就不能得到对象了。
name={} 可以省略,可以写为@Bean({"user1","userInfo1"})
package service;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserBean {
@Bean(name = {"user1","userInfo1"})
public UserInform getUser(){
UserInform userInform = new UserInform();
userInform.setId(1);
userInform.setName("小明");
return userInform;
}
}
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserInform;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
UserInform userInform = applicationContext.getBean("user1", UserInform.class);
UserInform userInform2 = applicationContext.getBean("userInfo1", UserInform.class);
System.out.println(userInform);
System.out.println(userInform2);
}
}
获取Bean对象也称为对象装配,是把对象取出来放到某个类中,也成为对象注入。
先将BookService对象存入到Spring中,再将对象从容器中拿出来。
package injectiontry.Service;
import org.springframework.stereotype.Service;
@Service //将BookService存入Spring中
public class BookService {
public void addBook(int bookId,String bookName){
System.out.println("书的信息是"+bookName+bookId);
}
}
package injectiontry.Controller;
import injectiontry.Service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class BookController {
// 通过属性注入的方式获得对象
@Autowired
private BookService bookService;
public void showBook(){
bookService.addBook(1,"三国");
}
}
import injectiontry.Controller.BookController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
BookController bookController = applicationContext.getBean("bookController",BookController.class);
bookController.showBook();
}
}
先使用类型进行查询,如果在Spring中查询到了同类型的对象就直接返回。否则使用类名称进行查询,如果两个都查询不到,那么注入失败,否则就为成功。
private BookService bookService;
@Autowired
public BookController(BookService bookService){
this.bookService = bookService;
}
当类中只有一个构造方法时,@Autowired可以省略掉,当有多个构造函数时,@Autowired不能省略。
@Autowired
public void getBookService(BookService bookService){
this.bookService = bookService;
}
属性注入的写法最简单,缺点:这种写法只适应于IoC容器,非IoC容器不能识别。
构造方法注入,是官方推荐的首选方案。缺点:代码比较多,看起来比较臃肿。优点是通用性比较好,代码的移植性比较高。
setter注入。通用性也比较好。是早期Spring推荐的注入方式。
private BookService bookService;
@Resource
public void getBookService(BookService bookService){
this.bookService = bookService;
}
出身不同:@Autowired来自Spring框架,@Resource来自JDK。
设置的参数不同:使用@Autowired可以设置的属性只有一个,而@Resource却有多个。
修饰对象不同:@Autowired可以用于属性注入、构造方法注入和Setter注入。而@Resource只能用在属性注入和setter注入,不能用于构造方法注入。
在Spring中注入了两个UserInform对象,可以通过 @Resource(name="")就可以获得。
package asd;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class UserBean {
@Bean({"user1"})
public UserInform getUser1(){
UserInform userInform = new UserInform();
userInform.setId(1);
userInform.setName("小明");
return userInform;
}
@Bean({"user2"})
public UserInform getUser2(){
UserInform userInform = new UserInform();
userInform.setId(2);
userInform.setName("小王");
return userInform;
}
}
package asd;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
@Configuration
public class USer {
@Resource(name = "user2")
private UserInform userInform;
public void showUser(){
System.out.println(userInform);
}
}
package asd;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
@Configuration
public class USer {
@Autowired
@Qualifier("user1")
private UserInform userInform;
public void showUser(){
System.out.println(userInform);
}
}
将对象存储到Spring中:
①存储bean对象的注解有5种:@Controller、@Service、@Repository、@Component、@Configuration。不同的类注解,用途不同。@controller负责业务逻辑层。验证前端参数是否合法。@Service是服务层,用于数据的组装和数据库接口的管理。@Repository是数据持久层。用于数据库的查询和管理。@Configuration是配置层。用于设置当前项目中所有的配置信息。@Component主要包含了一些实体类。其他四种注解都是@Component的子类。
②方法注解@Bean。出于对性能的考量,方法注解必须和类注解一起使用。方法注解支持重命名。可以给该方法返回的对象指定多个名称。
将对象从Spring中拿出:
使用@Autowired:可以用于属性注入、构造方法注入、和setter注入
使用@Resource:属性注入和setter注入
当同一个类型的对象被Spring多次注入,如何获取?
way1:@Resource(name="") way2:@Autowired+@Qualifier