目录
一、创建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. 总结
一、创建Spring项目
1. 创建一个普通的maven项目
2. 添加Spring框架支持(spring-context,spring-beans)
在项目的pom.xml中添加Spring框架的支持:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
</dependencies>
3. 添加启动类
在java文件夹下创建一个启动类,包含main方法
public class App {
public static void main(String[] args) {
}
}
二、Bean对象的读取和存储——不使用注释版
1. 创建Bean
Bean就是一个普通的对象。
public class User {
public String sayHi(String name){
return name + "hello!";
}
}
2. 将Bean注册到容器
添加Spring配置文件spring-config.xml(名字不能改),将文件放到resoources的根目录下。
我这里目录如下:
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
将User对象注册到Spring中,在<beans>中添加如下配置:
<beans>
<bean id = "user" class="Bean.User"></bean>
</beans>
修改后的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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id = "user" class="Bean.User"></bean>
</beans>
3. 获取并使用Bean对象
有以下3步:
- 创建Spring上下文。
- 获取指定的Bean对象。
- 使用Bean。
3.1 创建Spring上下文
有两种方式:
- 使用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 容器的。
3.2 获取指定的Bean对象
// 1.得到 Spring 上下⽂对象
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
// 2.加载某个 bean
User user = (User) context.getBean("user");
注意:Bean的Id要一一对应。
getBean方法的用法
(1). 根据类型获取Bean
UserController user = context.getBean(UserController.class);
(2). 名称+类型获取Bean
UserController user = context.getBean("user", UserController.class);
(3). 区别
当一个类型被重复注册到spring-config.xml中时,只能使用根据名称获取。
3.3 使用Bean
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"));
}
}
4. 总结步骤
1. 先得到容器。
2. 存对象
- 创建Bean(普通类)。
- 将Bean注册(配置)到spring-confing.xml中。
3. 取对象
- 得到 Spring 上下⽂,并读取到 Spring 的配置⽂件。
- 获取某⼀个 Bean 对象。
- 使⽤ Bean 对象。
三、Bean对象的读取和存储——使用注解版
1. 存储Bean对象
1.1 配置扫描路径
添加Spring配置文件spring-config.xml(名字不能改),将文件放到resoources的根目录下。
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="org.example"></content:component-scan>
</beans>
其中圈中的这一行为注册扫描的包,需要自己修改,我这里目录如图:
所以也就是说,即使添加了注解,如果不是在配置的扫描包下的类对象,也是不能被存储到Spring中的。
1.2 添加注解存储Bean对象
想要将对象存储在 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");
}
}
注意:
- 为什么需要这么多类注解?因为这样可以更方便让程序员看到注解后直接了解当前类的用途。
- 类注解之间的关系:@Controller、@Service、@Repository、@Configuration都是@Component的“子类”。
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;
}
}
2. 获取Bean对象(对象装配)
获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊。
对象装配(对象注⼊)的实现⽅法以下 3 种:
- 属性注⼊
- 构造⽅法注⼊
- Setter 注⼊
以将Service 类注⼊到 Controller 类中举例:
2.1 属性注入
属性注⼊是使⽤ @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");
}
}
输出:
2.2 构造方法注入
@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 来明确指定到底使⽤哪个构造⽅法,否则程序会报错。
2.3 Setter注入
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");
}
}
2.4 三种注入优缺点分析
- 属性注⼊的优点是简洁,使⽤⽅便;缺点是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指针异常)。
- 构造⽅法注⼊是 Spring 推荐的注⼊⽅式,它的缺点是如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,它的优点是通⽤性,在使⽤之前⼀定能把保证注⼊的类不为空。
- Setter ⽅式是 Spring 前期版本推荐的注⼊⽅式,但通⽤性不如构造⽅法,所有 Spring 现版本已经推荐使⽤构造⽅法注⼊的⽅式来进⾏类注⼊了。
2.5 @Resource:另一种注入关键字
@Controller
public class UserController4 {
@Resource
private UserService userService;
public void sayHi(String name){
System.out.println("HiController" + name);
userService.sayHi(name);
}
}
@Autowired 和 @Resource 的区别:
- 出身不同:@Autowired 来⾃于 Spring,⽽ @Resource 来⾃于 JDK 的注解;
- 使⽤时设置的参数不同:相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如name 设置,根据名称获取 Bean。
- @Autowired 可⽤于 Setter 注⼊、构造函数注⼊和属性注⼊,⽽ @Resource 只能⽤于 Setter 注⼊和属性注⼊,不能⽤于构造函数注⼊。
2.5 同⼀类型多个 Bean 报错处理
解决同⼀个类型,多个 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);
}
}
3. 总结
将对象存储到 Spring 中:
- 使⽤类注解:@Controller、@Service、@Repository、@Configuration、@Component【它们之间的关系】
- 使⽤⽅法注解:@Bean【注意事项:必须配合类注解⼀起使⽤】
Bean 的命名规则:
⾸字⺟和第⼆个字⺟都⾮⼤写,⾸字⺟⼩写来获取 Bean,如果⾸字⺟和第⼆个字⺟都是⼤写,那么直接使⽤原 Bean 名来获取 Bean。
从 Spring 中获取对象:
- 属性注⼊
- Setter 注⼊
- 构造函数注⼊
注⼊的关键字有:
- @Autowired
- @Resource
@Autowired 和 @Resource 区别:
- 出身不同;
- 使⽤时设置参数不同 @Resource ⽀持更多的参数,⽐如 name。
解决同⼀类型多个 Bean 的报错:
- 使⽤ @Resource(name="")
- 使⽤ @Qualifier("")