文章目录
- 1. 存储bean对象
- 1.1 使用配置文件存储bean对象
- 1.2 使用五大类注解存储bean对象
- 1.2.1 类注解
- 1.2.2 五大类注解的作用
- 1.2.3 方法注解
- 2.获取bean对象
- 2.1 属性注入
- 2.2 构造器注入
- 2.3 getter注入
- 2.4 注入对象的时候有`spring`中有多个`bean`对象怎么办
- 2.4.1 将类中属性的名字,改成和要注入的`bean`对象的名字一样
- 2.4.2 在 `@Autowired`注解下面加`@Qualifier`注解
- 2.4.3 抛弃`@Autowired`注解, 使用`@Resource`注解
- 2. 5 @Autowired和@Resource注解的区别
1. 存储bean对象
存储 Bean 分为以下 2 步:
- 存储 Bean 之前,先得有 Bean 才⾏,因此先要创建⼀个 Bean, 说白了也就是写一个类。
- 告诉spring,把这个类的对象存起来。
1.1 使用配置文件存储bean对象
- 编写
User
类, 有sayHi
方法。
public class User {
public void sayHi() {
System.out.println("你好");
}
}
- 告诉
spring
,把这个类的对象存起来。
在配置文件中可以通过<bean>
标签来告诉spring
把对象存起来。
<bean id="user1" class="demo.User"></bean>
id
: 是用来标识一个对象的,就像我们的身份证一样。
也称为bean对象的name(名字)
, 后面通过这个名字就能找到这个对象。class
:是带包的类名, 让spring
知道我们要存的是哪一个类的对象。
完整的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">
<bean id="user1" class="demo.User"></bean>
</beans>
注意:配置文件其他的标签不用管,直接复制粘贴,需要关注的是<bean>
标签。
怎么知道Spring
把对象存起来了呢?我们查找一下这个bean
对象的name
(名字) 就行了。
使用BeanFactory
或者ClassPathXmlApplicationContext
就能查找bean
对象了。
用BeanFactory
的代码如下:
public class Test {
public static void main(String[] args) {
//创建BeanFactory的实现类的对象
BeanFactory beanFactory =
new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
//根据名字查找bean对象
User user1 = (User)beanFactory.getBean("user1");
//调用sayHi()方法
user1.sayHi();
}
}
结果:
如何创建BeanFactory
对象:
BeanFactory
是一个接口,XmlBeanFactory
是其中的一个实现类,因为我们用xml
文件来告诉spring
存储bean
对象,所以用XmlBeanFactory
这个类。XmlBeanFactory
其中的一个构造器的参数类型是:Resource
。
Resource
也是一个接口, 所以还需要创建Resource
接口的实现类。
使用ClassPathXmlApplicationContext
上下文对象,查找bean
对象。
public class Test {
public static void main(String[] args) {
test2();
}
public static void test2() {
//创建上下文对象
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
//查找bean对象,第二个参数传了User的类型,得到bean对象后就无需转型了
User user1 = context.getBean("user1", User.class);
user1.sayHi();
}
}
结果:
1.2 使用五大类注解存储bean对象
用xml
的形式来存储对象会比较麻烦,如果需要存很多个对象,就需要在xml
配置文件中写多个<bean>
标签。
这样子会很麻烦。所以spring
提供了更加简便的方式来存储bean
对象, 那就是使用注解。
下面介绍使用注解存储bean
对象。
使用注解的方式,也要配置xml
文件,不过只需要配置一个标签:<content:component-scan>
配置文件如下:
<?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="demo"></content:component-scan>
</beans>
说明:
<content:component-scan>
这个标签用来配置包扫描路径, base-package="demo"
配置的就是具体的包。
作用就是告诉spring
在哪个包下扫描带有注解的类。spring
扫描到带有注解的类就会为这个类创建对象。
<content:component-scan base-package="demo"></content:component-scan>
想要将对象存储在 Spring 中,有两种注解类型可以实现:
- 类注解:
@Controller
(控制器)、@Service
(服务)、
@Repository
(仓库)、@Component
(组件)、@Configuration
(配置)。 - ⽅法注解:
@Bean
1.2.1 类注解
- 使用
@Controller
类注解
在下面的代码中创建了ControllerTest
类,有sayHello
方法,类的上面有@Controller
注解
有了这个@Controller
注解,spring
就能扫描到这个类,然后spring
就会创建对象了。
@Controller
public class ControllerTest {
public void sayHello() {
System.out.println("hello, 正在测试@Controller注解");
}
}
测试类:
public class Test {
public static void main(String[] args) {
test3();
}
public static void test3() {
//创建上下文对象
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
//获取bean对象, 如果没有在注解上加参数,默认用类名的首字母小写获取bean对象
ControllerTest controllerTest = context.getBean("controllerTest", ControllerTest.class);
controllerTest.sayHello();
}
结果:
注意:
如果在注解上没有指定bean
对象的名字,将类名的首字母小写后作为bean
对象的名字获取bean
对象。
ControllerTest
类名小写后是controllerTest
,所以用controllerTest
可以获取到bean
对象。
也可以在注解上传参,指定bean
对象的名字。
根据名字获取bean
对象
- 使用
@Service
注解
@Service
注解跟@Controller
的用法几乎一模一样。
@Service
public class ServiceTest {
public void sayHello() {
System.out.println("hello, 正在测试@Service注解");
}
}
public class Test {
public static void main(String[] args) {
test4();
}
public static void test4() {
//创建上下文对象
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
//获取bean对象, 如果没有在注解上加参数,默认用类名的首字母小写获取bean对象
ServiceTest serviceTest = context.getBean("serviceTest", ServiceTest.class);
serviceTest.sayHello();
}
}
@Repository
, @Component
, @Configuarion
注解用法跟上面的代码差不多,就不再演示了。
1.2.2 五大类注解的作用
因为后端程序是分层的,这五个类注解,分别就代表不同的层。
@Controller
代表了业务逻辑层。
@Service
代表了服务层。
@Repository
代表了数据层。
@Configuration
是配置层。
这些类注解功能是一样的,都是告诉spring
存储bean
对象。
但是当我们看到一个类上带了@Controller
注解的时候,我们就清楚了,这个类处于 哪一层的,是干什么的。
这样做这样可以大大提高程序的可阅读性。
1.2.3 方法注解
@Bean
方法注解用来将方法返回的对象存到spring
中。
在ControllerTest
类中,写一个getObj
方法,这个方法返回的ArrayList
对象会存到spring
中
@Controller("con")
public class ControllerTest {
public void sayHello() {
System.out.println("hello, 正在测试@Controller注解");
}
@Bean(name = "list")
public ArrayList<Integer> getObj() {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
return list;
}
}
测试列:
public class Test {
public static void main(String[] args) {
test5();
}
public static void test5() {
//创建上下文对象
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
//根据name获取bean对象
ArrayList<Integer> list = context.getBean("list", ArrayList.class);
System.out.println(list.get(0));
}
}
输出:
2.获取bean对象
获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,也可以叫对象注⼊。
对象注⼊的实现⽅法以下 3 种:
- 属性注⼊
- 构造⽅法注⼊
- Setter 注⼊
使用@Autowired
或者@Resource
注解实现spring中的bean对象注入。
这里用@Autowired
注解进行演示。
2.1 属性注入
UserService
类
@Service
public class UserService {
public void sayHi() {
System.out.println("Hi");
}
}
UserController
类
获取spring
中的对象使用@Autowired
注解,将UserService
类的bean
对象注入进来
@Controller
public class UserController {
@Autowired
private UserService userService;
public void sayHi() {
userService.sayHi();
}
}
测试类:
public class Test {
public static void main(String[] args) {
test6();
}
public static void test6() {
//创建上下文对象
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
//获取bean对象
UserController userController = context.getBean("userController", UserController.class);
userController.sayHi();
}
}
输出了Hi
,UserSevice
类的bean
对象成功被注入了。
2.2 构造器注入
将@Autowired
注解放在构造器的上面,加一个形参,就可以实现构造器注入了。
@Controller
public class UserController {
private UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
public void sayHi() {
userService.sayHi();
}
}
2.3 getter注入
getter
注入也一样,将@Autowired
注解放在getter
方法上即可。
@Controller
public class UserController {
private UserService userService;
public void sayHi() {
userService.sayHi();
}
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
}
2.4 注入对象的时候有spring
中有多个bean
对象怎么办
当注入对象的时候,spring
中有多个对象的时候,就要告诉spring
获取的是哪个bean
对象。
但是@Autowired
注解不能传入bean
对象的名字,所以要用其他的方式来解决这个问题。
这时候有三种做法:
- 将类中属性的名字,改成和要注入的
bean
对象的名字一样 - 在
@Autowired
注解下面加@Qualifier
注解 - 抛弃
@Autowired
注解, 使用@Resource
注解
下面演示这三种不同处理方法:
2.4.1 将类中属性的名字,改成和要注入的bean
对象的名字一样
Student
类, 有id
、name
、age
属性, set
方法和toString
方法。
public class Student {
private int id;
private String name;
private int age;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
StudentService
类, 使用了方法注解@Bean
将两个Student类
的对象存到spring
中。
@Service
public class StudentService {
@Bean("stu1")
public Student getStu1() {
Student student = new Student();
student.setId(1);
student.setName("张三");
student.setAge(22);
return student;
}
@Bean("stu2")
public Student getStu2() {
Student student = new Student();
student.setId(2);
student.setName("李四");
student.setAge(23);
return student;
}
}
StudentController
类中,有属性stu1
和showStuInfo
方法, 使用@Autowired
将对象注入到属性上。
@Controller("stucon")
public class StudentController {
@Autowired
private Student stu1;
public void showStuInfo() {
System.out.println(stu1.toString());
}
}
stu1属性名和bean对象的名字一样。
测试类:
public class Test {
public static void main(String[] args) {
test7();
}
public static void test7() {
//创建上下文对象
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
StudentController studentController = context.getBean("stucon", StudentController.class);
studentController.showStuInfo();
}
}
输入出:
2.4.2 在 @Autowired
注解下面加@Qualifier
注解
@Qualifier
注解的源码,使用注解的时候,可以传递value
的值
在@Qualifier
注解的中加上bean
对象的名字,spring
就知道要注入哪一个bean
对象了。
StudentController
类如下。
@Controller("stucon")
public class StudentController {
@Autowired
@Qualifier("stu1")
private Student stu;
public void showStuInfo() {
System.out.println(stu.toString());
}
}
2.4.3 抛弃@Autowired
注解, 使用@Resource
注解
@Resource
注解的部分源码。
在注解上传递一个参数即可,name = "stu1"
就表示要注入名为stu1
的bean
对象
@Controller("stucon")
public class StudentController {
@Resource(name = "stu1")
private Student stu;
public void showStuInfo() {
System.out.println(stu.toString());
}
}
2. 5 @Autowired和@Resource注解的区别
- 出身不同。
@Autowired
来自于spring
,而@Resource
是JDK
自带的。 - 传参不同。
@Resource
相比@Autowired
,可以传递的参数更多。 @Autowired
注解可以用于属性注入,构造方法注入,setter注入。
而@Resource
注解只能用于属性注入和setter注入, 不同用于构造方法注入。
因为@Autowried
注解可以修饰属性,构造器,和方法,@Resource
不能修饰构造器,但可以修饰属性和方法。
@Autowried
注解部分源码
@Resource
注解部分源码