目录
一、创建Spring项目
1. 创建一个普通的maven项目
2. 添加Spring框架支持(spring-context,spring-beans)
3. 添加启动类
二、Bean对象的读取和存储——不使用注释版
1. 创建Bean
2. 将Bean注册到容器
3. 获取并使用Bean对象
3.1 创建Spring上下文
3.2 获取指定的Bean对象
getBean方法的用法
3.3 使用Bean
4. 总结步骤
三、Bean对象的读取和存储——使用注解版
1. 存储Bean对象
1.1 配置扫描路径
1.2 添加注解存储Bean对象
2. 获取Bean对象(对象装配)
2.1 属性注入
2.2 构造方法注入
2.3 Setter注入
2.4 三种注入优缺点分析
2.5 @Resource:另一种注入关键字
2.5 同⼀类型多个 Bean 报错处理
3. 总结
在项目的pom.xml中添加Spring框架的支持:
org.springframework
spring-context
5.2.3.RELEASE
org.springframework
spring-beans
5.2.3.RELEASE
在java文件夹下创建一个启动类,包含main方法
public class App {
public static void main(String[] args) {
}
}
Bean就是一个普通的对象。
public class User {
public String sayHi(String name){
return name + "hello!";
}
}
添加Spring配置文件spring-config.xml(名字不能改),将文件放到resoources的根目录下。
我这里目录如下:
spring-config.xml(固定格式,无需记忆,保存到能找到的地方):
将User对象注册到Spring中,在
修改后的spring-config.xml:
有以下3步:
- 创建Spring上下文。
- 获取指定的Bean对象。
- 使用Bean。
有两种方式:
- 使用ApplicationContext
- 使用BeanFactory
(1). 使用ApplicationContext
// 1.得到 Spring 的上下⽂对象,创建的时候需要配置 Spring 配置信息
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
(2). 使用BeanFactory
BeanFactory beanFactory = new XmlBeanFactory(newClassPathResource("springconfig.xml"));
(3). ApplicationContext和BeanFactory
ApplicationContext和BeanFactory的效果是一样的,ApplicationContext属于BeanFactory的子类。
- 继承关系和功能方面:Spring容器有两个顶级接口: ApplicationContext和BeanFactory。其中BeanFactory提供了基础的访问容器的能力,而ApplicationContext属于BeanFactory的子类,除了继承BeanFactory的所有功能之外,它还拥有独特的特性,添加了对国际化支持,资源访问支持,以及事件传播等方面的支持。
- 性能方面:ApplicationContext是一次性加载并初始化所有Bean对象,而BeanFactory是需要哪个才去加载哪个,因此更加轻量。
PS:ClassPathXmlApplicationContext 属于 ApplicationContext 的⼦类,拥有ApplicationContext 的所有功能,是通过 xml 的配置来获取所有的 Bean 容器的。
// 1.得到 Spring 上下⽂对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.加载某个 bean
User user = (User) context.getBean("user");
注意:Bean的Id要一一对应。
(1). 根据类型获取Bean
UserController user = context.getBean(UserController.class);
(2). 名称+类型获取Bean
UserController user = context.getBean("user", UserController.class);
(3). 区别
当一个类型被重复注册到spring-config.xml中时,只能使用根据名称获取。
public class App {
public static void main(String[] args) {
// 1.得到 Spring 的上下⽂对象,创建的时候需要配置 Spring 配置信息
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.加载某个bean
User user = (User) context.getBean("user");
// 3.调用相应方法
System.out.println(user.sayHi("Java"));
}
}
1. 先得到容器。
2. 存对象
3. 取对象
添加Spring配置文件spring-config.xml(名字不能改),将文件放到resoources的根目录下。
spring-config.xml:
其中圈中的这一行为注册扫描的包,需要自己修改,我这里目录如图:
所以也就是说,即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到Spring中的。
想要将对象存储在 Spring 中,有两种注解类型可以实现:
- 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
- ⽅法注解:@Bean。
1.2.1 类注解
(1). @Controller——控制器存储,表示业务逻辑层
@Controller
public class UserController {
public void sayHi(String name){
System.out.println("HiController" + name);
}
}
public class Main {
public static void main(String[] args) {
//1. Controller
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
UserController userController = (UserController) context.getBean("userController");
// 3.调⽤ bean ⽅法
userController.sayHi("Controller");
}
}
(2). @Service——服务存储
@Service
public class UserService {
public void sayHi(String name){
System.out.println("HiService" + name);
}
}
public class Main {
public static void main(String[] args) {
//2. Service
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
UserService userService = (UserService) context.getBean("userService");
// 3.调⽤ bean ⽅法
userService.sayHi("Service");
}
}
(3). @Repository——仓库存储(数据库)
@Repository
public class UserRepository {
public void sayHi(String name){
System.out.println("HiRepository" + name);
}
}
public class Main {
public static void main(String[] args) {
//3. Repository
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
UserRepository userRepository = (UserRepository) context.getBean("userRepository");
// 3.调⽤ bean ⽅法
userRepository.sayHi("Repository");
}
}
(4). @Component——组件存储
@Component
public class UserComponent {
public void sayHi(String name){
System.out.println("HiComponent" + name);
}
}
public class Main {
public static void main(String[] args) {
//4. Component
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
UserComponent userComponent = (UserComponent) context.getBean("userComponent");
// 3.调⽤ bean ⽅法
userComponent.sayHi("Component");
}
}
(5). @Configuration——配置存储
@Configuration
public class UserConfiguration {
public void sayHi(String name){
System.out.println("HiConfiguration" + name);
}
}
public class Main {
public static void main(String[] args) {
//5. Configuration
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
UserConfiguration userConfiguration = (UserConfiguration) context.getBean("userConfiguration");
// 3.调⽤ bean ⽅法
userConfiguration.sayHi("Configuration");
}
}
注意:
Bean的命名规则:
1. 类名前两个字母只有首字母大写,读取时将首字母改为小写。
2. 类名前两个字母都是大写,读取时保持不变。
1.2.2 方法注解@Bean
类注解是添加到某个类上的,方法注解是放到某个方法上的。
⽅法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中。
1.2.2.1 使用
@Component
public class Users {
@Bean
public User user1() {
User user = new User();
user.sayHi("Java");
return user;
}
}
public class Main2 {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
User user = (User) context.getBean("user1");
// 3.调⽤ bean ⽅法
user.sayHi("hhh");
}
}
1.2.2.2 重命名Bean
@Component
public class Users {
@Bean(name ={"u1"})
public User user1() {
User user = new User();
user.sayHi("Java");
return user;
}
}
public class Main2 {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
User user = (User) context.getBean("u1");
// 3.调⽤ bean ⽅法
user.sayHi("hhh");
}
}
这个重命名的 name 其实是⼀个数组,⼀个 bean 可以有多个名字:
@Component
public class Users {
@Bean(name = {"u1","us1"})
public User user1() {
User user = new User();
user.sayHi("Java");
return user;
}
}
并且 name= 可以省略,如下所示:
@Component
public class Users {
@Bean({"u1","us1"})
public User user1() {
User user = new User();
user.sayHi("Java");
return user;
}
}
获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊。
对象装配(对象注⼊)的实现⽅法以下 3 种:
- 属性注⼊
- 构造⽅法注⼊
- Setter 注⼊
以将Service 类注⼊到 Controller 类中举例:
属性注⼊是使⽤ @Autowired 实现的。
Service类:
@Service
public class UserService {
public void sayHi(String name){
System.out.println("HiService" + name);
}
}
Controller类:
@Controller
public class UserController {
public void sayHi(String name){
System.out.println("HiController" + name);
userService.sayHi(name);
}
//属性注入
@Autowired
private UserService userService;
}
public class Main3 {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
UserController userController = (UserController) context.getBean("userController");
// 3.调⽤ bean ⽅法
userController.sayHi("Controller");
}
}
输出:
@Controller
public class UserController2 {
//构造方法注入
private UserService userService;
@Autowired
public UserController2(UserService userService){
this.userService = userService;
}
public void sayHi(String name){
System.out.println("HiController" + name);
userService.sayHi(name);
}
}
public class Main4 {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
UserController2 userController2 = (UserController2) context.getBean("userController2");
// 3.调⽤ bean ⽅法
userController2.sayHi("Controller2");
}
}
注意:
如果只有⼀个构造⽅法,那么 @Autowired 注解可以省略,但是如果类中有多个构造⽅法,那么需要添加上 @Autowired 来明确指定到底使⽤哪个构造⽅法,否则程序会报错。
Setter 注⼊和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注解。
@Controller
public class UserController3 {
//Setter注入
private UserService userService;
@Autowired
public void setUserService(UserService userService){
this.userService = userService;
}
public void sayHi(String name){
System.out.println("HiController" + name);
userService.sayHi(name);
}
}
public class Main5 {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean 默认类名首字母小写
UserController3 userController3 = (UserController3) context.getBean("userController3");
// 3.调⽤ bean ⽅法
userController3.sayHi("Controller3");
}
}
@Controller
public class UserController4 {
@Resource
private UserService userService;
public void sayHi(String name){
System.out.println("HiController" + name);
userService.sayHi(name);
}
}
@Autowired 和 @Resource 的区别:
解决同⼀个类型,多个 bean 的解决⽅案有以下两个:
- 使⽤ @Resource(name="user1") 定义。
- 使⽤ @Qualifier(value = "user2") 注解定义名称。
@Component
public class Users {
@Bean
public User user1() {
User user = new User();
user.sayHi("user1");
return user;
}
@Bean
public User user2() {
User user = new User();
user.sayHi("user2");
return user;
}
}
2.5.1 使用 @Resource(name="user1") 定义
@Controller
public class UserController5 {
@Resource(name = "user1")
private User user;
public void sayHi(String name){
System.out.println("HiController" + name);
user.sayHi(name);
}
}
2.5.2 使用 @Qualifier(value = "user2") 注解定义名称
@Controller
public class UserController5 {
@Autowired
@Qualifier("user2")
private User user;
public void sayHi(String name){
System.out.println("HiController" + name);
user.sayHi(name);
}
}
将对象存储到 Spring 中:
- 使⽤类注解:@Controller、@Service、@Repository、@Configuration、@Component【它们之间的关系】
- 使⽤⽅法注解:@Bean【注意事项:必须配合类注解⼀起使⽤】
Bean 的命名规则:
⾸字⺟和第⼆个字⺟都⾮⼤写,⾸字⺟⼩写来获取 Bean,如果⾸字⺟和第⼆个字⺟都是⼤写,那么直接使⽤原 Bean 名来获取 Bean。
从 Spring 中获取对象:
- 属性注⼊
- Setter 注⼊
- 构造函数注⼊
注⼊的关键字有:
- @Autowired
- @Resource
@Autowired 和 @Resource 区别:
- 出身不同;
- 使⽤时设置参数不同 @Resource ⽀持更多的参数,⽐如 name。
解决同⼀类型多个 Bean 的报错:
- 使⽤ @Resource(name="")
- 使⽤ @Qualifier("")