前言
上一篇博客简单的介绍了spring的功能与使用,可以看到我们创建一个对象,就需要在xml中存储一个bean对象,这种操作非常的繁琐,因此spring发明了使用注解来快捷存储bean对象
配置工作
我们在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="">
</content:component-scan>
</beans>
其中base-package=""中填写要存储的包路径,比如我们的对象存储在com.demo.controller路径下,那么就填写
<content:component-scan base-package="com.demo.component">
</content:component-scan>
存储Bean对象
有多种注解可以存储对象
- 类注解:@Controller @Service @Repository @Component @Configuration
- @Bean
@Controller
在类上使用@Controller 注解,就可以存储bean对象
package com.demo.component;
import org.springframework.stereotype.Controller;
@Controller
public class ArticleController {
public String sayHi(){
return "hi";
}
}
获取使用bean对象和之前的方法一样,使用ApplicationContext
spring规定,使用类名的小驼峰作为id,因此我们可以通过下面这种格式获取bean对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
ArticleController articleController = context.getBean("articleController", ArticleController.class);
System.out.println(articleController.sayHi());
如果我们的类名本身首字母就是小写的,那么获取Bean的名称和类名一样,如果我们的类名第一个字母和第二个字母都是大写字母,比如说AApple,那么Spring规定,也是使用原类名来获取Bean对象
如果我们的类直接创建于java包下,而不是自定义的包下,我们想要将这个类注入到Spring中,那么要按照下面这个方法来操作
将扫描目录改为通配符**,使用通配符,可以扫描所有的这个项目下所有的类文件
<content:component-scan base-package="**">
</content:component-scan>
并且,我们在main方法调用时,必须使用BeanFactory来获取上下文
BeanFactory factory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));
User user = (User) factory.getBean("user");
System.out.println(user.sayHi());
但是可以发现,使用这个方法,执行的速度是非常慢的,因此非常不建议大家这样编写
其他类注解
使用其他四个类注解,也可以实现和@Controller相同的功能,其基本原理和实现方式和Controller是一样的,事实上,@Component是其他四个类注解的父类
package com.demo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StudentService {
public void sayHi(){
System.out.println("service : hi");
}
}
在我们的Spring core中,这些类注解的用途都是一样的,只有后面的Spring MVC和SpringBoot中,这些类注解才有他们不同的功能
分成五个不同类注解的原因:
- 我们可以通过类注解来判断这个类是用来干嘛的
- 五个类在SpringMVC和SpringBoot中有不同的功能
下面来简单介绍一下这五大类注解的用途:
当我们用户在前端访问网站时,@Controller对应的类负责接待这些用户,确认用户的参数是否合理,相当于我们进餐厅后的接待员,会把你领到位置上
接着,数据传给@Service对应的类,负责判断前端的请求需要调用什么功能,相当于餐厅的服务员,会把你想要的菜告诉后厨
然后,数据传给@Repository对应的类,其于数据库直接相连,会操作数据库的增删改查,相当于餐厅中的厨师,会把饭给你做好拿出来
而@Configuration对应的类,用来配置项目的一些信息
@Component对应的类,则提供一些项目中的公共方法,例如我们项目中确认用户是否登陆,整个项目都需要这个方法
下面来简单翻译一下这些词的含义
- @Component 组件,归属于公共工具类
- @Controller 控制器, 归属于业务逻辑层
- @Service 服务,归属于服务层
- @Repository 仓库,归属于持久层
- @Configuration 配置,归属于配置层
@Bean
除了在类上使用五大类注解,可以在Spring中存储这个类,我们还可以在方法上使用@Bean这个注解,可以将方法的返回对象存储在Spring中
需要注意的是,为了防止需要扫描大量的方法,因此@Bean在方法上注解了后,还需要在这个方法对应的类上使用五大类注解
代码实例:
我们在别的包实现student类
package com.demo.model;
public class Student {
private int age;
private int id;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", id=" + id +
'}';
}
}
然后在一个返回Student的方法上注解@Bean,在整个类上注解五大类注解
package com.demo.component;
import com.demo.model.Student;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class StudentBean {
@Bean
public Student student(){
Student student = new Student();
student.setId(1);
student.setAge(1);
return student;
}
}
就可以使用上下文对象来获取Student对象了
Student student = context.getBean("student",Student.class);
System.out.println(student);
其id和五大类注解一样,默认是类名的小驼峰,由于方法可能有很多重名的,因此我们可以在@Bean后设置name属性,还可以设置多个
@Bean(name = {"stu","学生","s"})
在设置name属性后,原先的小驼峰就找不到对应的类了
属性注入
按照前面讲的,我们需要将@Service的类注入到@Controller类中,那么我们就可以使用属性注入
先实现一个StudentService类
package com.demo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StudentService {
public void sayHi(){
System.out.println("service : hi");
}
}
在StudentController类中,就可以自动的获取studentService对象
package com.demo.controller;
import com.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class StudentController {
@Autowired
private StudentService studentService;
public void sayHi(){
studentService.sayHi();
}
}