Spring框架-Spring Bean管理
文章目录
Spring Bean管理
Spring Bean
通过之前的学习对SpringBean有了简单的认识。下面详细介绍一下SpringBean。
Spring Bean是任何由Spring容器管理的对象。可以通过配置文件,注解或者Java代码进行配置和创建。
在Spring中,Bean是Spring容器中的基本单位,Spring容器负责管理所有的Bean,包括创建,初始化,配置,销毁和依赖注入等。所有我们掌握bean的概念和使用方法对于理解和应用Spring框架是非常重要的。
Bean的定义
在Spring中,Bean的定义通常包括以下几个元素:
- ID:Bean的唯一标识符。
- Class:Bean的类型,通常是一个Java类。
- Scope:Bean的作用域,通常有单例(Singleton)、原型(Prototype)、会话(Session)和请求(Request)四种。默认为单例。
- Constructor arguments:Bean的构造函数参数。
- Properties:Bean的属性。
Bean的依赖注入
在Spring中,依赖注入是一种将对象之间的依赖关系交给Spring容器管理的方式。当一个Bean需要使用另一个Bean时,它只需声明一个对该Bean的引用,并由Spring容器负责注入该Bean的实例。
Spring支持多种注入方式,包括构造函数注入、Setter方法注入、字段注入和接口注入等。其中,构造函数注入和Setter方法注入是最常用的两种方式。
配置方式:
Spring提供了多种方式来配置和创建Bean,包括XML配置、注解配置和Java配置。具体方法如下:
- XML配置:通过在XML配置文件中定义Bean的标签和属性,可以告诉Spring如何创建和管理Bean。
- 注解配置:通过在Bean的类上添加注解来告诉Spring如何创建和管理Bean。
- Java配置:通过编写Java类来告诉Spring如何创建和管理Bean。
使用XML配置方式:
User.java
package com.sin.pojo;
/**
* @createTime 2024/1/2 15:56
* @createAuthor SIN
* @use
*/
public class User {
private String name;
private int age;
public User(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><!-- XML声明,xml版本和编码格式 -->
<!-- spring配置文件起点 -->
<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">
<!-- 创建一个名为user的bean,对应的类是com.sin.pojo.User -->
<bean id="user" class="com.sin.pojo.User">
<!--
通过构造方法注入两个参数值,
0索引是String name,参数值为张三
1索引是int age ,参数只为20
-->
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" value="20"/>
</bean>
</beans>
UserTest.java
package com.sin.test;
import com.sin.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @createTime 2024/1/2 16:00
* @createAuthor SIN
* @use
*/
public class UserTest {
@Test
public void test() {
// 加载Spring配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 获取bean
User user = (User) context.getBean("user");
// 使用bean输出数据
System.out.println("姓名:" + user.getName());
System.out.println("年龄:" + user.getAge());
}
}
使用注解配置方式:
通过在Bean的类上添加注解来告诉Spring如何创建和管理Bean,常见的注解有:
注解 | 说明 |
---|---|
@Component | 是Spring框架的基本注解之一,用于将一个类标识为组件(Component)。被@Component 注解标记的类将会被Spring容器自动扫描,并创建对应的Bean。它通常用于标记普通的Java类,表示这些类需要由Spring进行管理。 |
@Service | 是@Component 注解的一个特化版本,用于标记一个类为服务(Service)层的组件。它表示该类是业务逻辑的实现类,通常用于在应用程序的服务层中使用。被@Service 注解标记的类将被自动注册为Bean,并可以通过依赖注入在其他类中使用。 |
@Repository | 是@Component 注解的一个特化版本,用于标记一个类为持久层(Repository)的组件。它表示该类用于访问和操作数据库或其他数据存储。被@Repository 注解标记的类将被自动注册为Bean,并可以通过依赖注入在其他类中使用。 |
@Autowired | 是Spring框架的依赖注入注解,用于自动装配Bean之间的依赖关系。当一个类需要使用其他的Bean时,可以使用@Autowired 注解在成员变量、构造方法或Setter方法上,Spring容器会自动将合适的Bean注入进来。通过@Autowired ,我们可以避免手动实例化对象或配置Bean之间的关联关系。 |
@Configuration | 将一个类声明为配置类,用于定义应用程序的配置信息。通常与@Bean 一起使用。 |
@Bean | 在配置类中使用该注解定义一个Bean。可以通过方法返回一个对象,并指定Bean的名称和类型。 |
@Scope | 用于指定Bean的作用域,即Bean的生命周期范围,如单例、原型等。常见的作用域包括Singleton (默认)、Prototype 、Request 、Session 等。 |
@Value | 用于注入配置值或表达式到Bean属性中。可以用于从配置文件中获取值,或者使用SpEL表达式进行计算。 |
@Qualifier | 用于指定要注入的Bean的名称,当存在多个同类型的Bean时,可以通过该注解指定要注入的具体Bean。 |
@Primary | 用于标识某个Bean为首选的Bean,当存在多个同类型的Bean时,优先选择被@Primary 注解标识的Bean。 |
@Component
UserService.java
package com.sin.service;
import org.springframework.stereotype.Component;
/**
* @createTime 2024/1/2 16:42
* @createAuthor SIN
* @use
*/
@Component
public class UserService {
public String getUserInfo(){
return "User information";
}
}
UserTest.java
package com.sin.test;
import com.sin.pojo.User;
import com.sin.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @createTime 2024/1/2 16:00
* @createAuthor SIN
* @use
*/
public class UserTest {
@Test
public void test() {
// 加载Spring配置文件
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册UserService类
context.register(UserService.class);
// 启动Spring容器
context.refresh();
// 从容器中获取UserService实例
UserService userService = context.getBean(UserService.class);
System.out.println(userService.getUserInfo());
// 关闭Spring容器
context.close();
}
}
@Service
UserService.java
package com.sin.service;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/1/2 16:42
* @createAuthor SIN
* @use
*/
@Service
public class UserService {
public String getUserInfo(){
return "User information";
}
}
UserTest.java
package com.sin.test;
import com.sin.pojo.User;
import com.sin.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @createTime 2024/1/2 16:00
* @createAuthor SIN
* @use
*/
public class UserTest {
@Test
public void test() {
// 加载Spring配置文件
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册包含@Service注解的类所在的包路径
context.scan("com.sin.service");
// 启动Spring容器
context.refresh();
// 从容器中获取UserService实例
UserService userService = context.getBean(UserService.class);
System.out.println(userService.getUserInfo());
// 关闭Spring容器
context.close();
}
}
@Repository
UserDao.java
package com.sin.dao;
import org.springframework.stereotype.Repository;
/**
* @createTime 2024/1/2 16:58
* @createAuthor SIN
* @use
*/
@Repository
public class UserDao {
public String getUserInfo(){
return "从数据库中查找数据";
}
}
UserService.java
package com.sin.service;
import com.sin.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/1/2 16:42
* @createAuthor SIN
* @use
*/
@Service
public class UserService {
@Autowired
private UserDao userDao;
public String getUserInfo(){
return userDao.getUserInfo();
}
}
UserTest.java
package com.sin.test;
import com.sin.pojo.User;
import com.sin.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @createTime 2024/1/2 16:00
* @createAuthor SIN
* @use
*/
public class UserTest {
@Test
public void test() {
// 加载Spring配置文件
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册包含@Repository注解的类所在的包路径
context.scan("com.sin.dao");
// 注册包含@Service注解的类所在的包路径
context.scan("com.sin.service");
// 启动Spring容器
context.refresh();
// 从容器中获取UserService实例
UserService userService = context.getBean(UserService.class);
System.out.println(userService.getUserInfo());
// 关闭Spring容器
context.close();
}
}
@Configuration
UserDao.java
package com.sin.dao;
import org.springframework.stereotype.Repository;
/**
* @createTime 2024/1/2 16:58
* @createAuthor SIN
* @use
*/
@Repository
public class UserDao {
public String getUserInfo(){
return "从数据库中查找数据";
}
}
UserService.java
package com.sin.service;
import com.sin.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/1/2 16:42
* @createAuthor SIN
* @use
*/
@Service
public class UserService {
@Autowired
private UserDao userDao;
public String getUserInfo(){
return userDao.getUserInfo();
}
}
AppConfig.java
package com.sin.config;
import com.sin.dao.UserDao;
import com.sin.service.GreetingService;
import com.sin.service.UserService;
import com.sin.service.impl.GreetingServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @createTime 2024/1/2 10:56
* @createAuthor SIN
* @use
*/
@Configuration
@ComponentScan// 启动组件扫描,自动注册待用@Respository和@Service注解的类到Spring容器中
public class AppConfig {
@Bean("userDao")
public UserDao userDao(){
return new UserDao();
}
@Bean("userService")
public UserService userService(){
return new UserService();
}
}
AppTest.java
package com.sin.test;
import com.sin.config.AppConfig;
import com.sin.service.UserService;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @createTime 2024/1/2 17:14
* @createAuthor SIN
* @use
*/
public class AppTest {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
System.out.println(userService.getUserInfo());
context.close();
}
}
@Scope
MyBean.java
package com.sin.pojo;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* @createTime 2024/1/3 8:35
* @createAuthor SIN
* @use
*/
@Component
@Scope("prototype")
public class MyBean {
private String name;
public MyBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Scope
是 Spring 框架中用于设置 bean 的作用域的注解之一。通过使用 @Scope
注解,我们可以指定 bean 的实例是单例(Singleton)还是原型(Prototype)等不同的作用域。
以下是 @Scope
注解的一些常见用法:
@Scope("singleton")
:默认选项,表示 bean 是单例的,Spring 容器将只创建并管理一个 bean 实例。@Scope("prototype")
:表示 bean 是原型的,每次从容器中获取该 bean 时都会创建一个新的实例。@Scope("request")
:表示 bean 的生命周期与 HTTP 请求的生命周期相同,在每个请求处理过程中创建一个新的 bean 实例,并在请求结束后销毁。@Scope("session")
:表示 bean 的生命周期与 HTTP 会话的生命周期相同,在每个会话期间创建一个新的 bean 实例,并在会话结束后销毁。@Scope("globalSession")
:表示 bean 的生命周期与全局 HTTP 会话的生命周期相同,仅在使用基于 Portlet 的 web 应用程序时才有效。
AppConfig.java
package com.sin.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @createTime 2024/1/2 10:56
* @createAuthor SIN
* @use
*/
@Configuration
@ComponentScan(basePackages = "com.sin.pojo") // 扫描组件
public class AppConfig {
}
AppTest.java
package com.sin.test;
import com.sin.config.AppConfig;
import com.sin.pojo.MyBean;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @createTime 2024/1/3 8:41
* @createAuthor SIN
* @use
*/
public class AppTest {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean bean1 = context.getBean(MyBean.class);
bean1.setName("张三");
System.out.println(bean1.getName());
MyBean bean2 = context.getBean(MyBean.class);
bean2.setName("李四");
System.out.println(bean2.getName());
}
}
@Value
app.properties
app.name : lisi
MyBean.java
package com.sin.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* @createTime 2024/1/3 8:35
* @createAuthor SIN
* @use
*/
@Component
public class MyBean {
@Value("李四")
private String name;
@Value("${app.name}")// 调用app.properties中的app.name
private String username;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
AppConfig.java
package com.sin.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @createTime 2024/1/2 10:56
* @createAuthor SIN
* @use
*/
@Configuration
@ComponentScan(basePackages = "com.sin.pojo") // 扫描组件
@PropertySource("classpath:app.properties")// 指定属性文件的位置或者其他属性值的类型和名称,以便让spring加载其中定义的属性值
public class AppConfig {
}
AppTest.java
package com.sin.test;
import com.sin.config.AppConfig;
import com.sin.pojo.MyBean;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @createTime 2024/1/3 8:41
* @createAuthor SIN
* @use
*/
public class AppTest {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyBean bean1 = context.getBean(MyBean.class);
System.out.println(bean1.getName());
System.out.println(bean1.getUsername());
}
}
@Qualifier
UserService.java
package com.sin.service;
/**
* @createTime 2024/1/3 9:10
* @createAuthor SIN
* @use
*/
public interface UserService {
public void addUser(String username);
}
UserServiceImpl1.java
package com.sin.service.impl;
import com.sin.service.UserService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/1/3 9:10
* @createAuthor SIN
* @use
*/
@Service
@Qualifier("userServiceImpl1")
public class UserServiceImpl1 implements UserService {
@Override
public void addUser(String username) {
System.out.println("添加的数据为"+ username + "位于 userServiceImpl1");
}
}
UserServiceImpl2.java
package com.sin.service.impl;
import com.sin.service.UserService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/1/3 9:12
* @createAuthor SIN
* @use
*/
@Service
@Qualifier("userServiceImpl2")
public class UserServiceImpl2 implements UserService {
@Override
public void addUser(String username) {
System.out.println("添加的数据为"+ username + "位于 userServiceImpl2");
}
}
AppConfig.java
package com.sin.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @createTime 2024/1/2 10:56
* @createAuthor SIN
* @use
*/
@Configuration
@ComponentScan(basePackages = "com.sin.pojo") // 扫描组件
public class AppConfig {
}
AppTest.java
package com.sin.test;
import com.sin.config.AppConfig;
import com.sin.pojo.UserServiceClient;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @createTime 2024/1/3 8:41
* @createAuthor SIN
* @use
*/
public class AppTest {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserServiceClient userServiceClient = context.getBean(UserServiceClient.class);
userServiceClient.addUser("张三");
}
}
@Primary
UserService.java
package com.sin.service;
/**
* @createTime 2024/1/3 9:10
* @createAuthor SIN
* @use
*/
public interface UserService {
public void addUser(String username);
}
UserServiceImpl1.java
package com.sin.service.impl;
import com.sin.service.UserService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/1/3 9:10
* @createAuthor SIN
* @use
*/
@Service
public class UserServiceImpl1 implements UserService {
@Override
public void addUser(String username) {
System.out.println("添加的数据为"+ username + "位于 userServiceImpl1");
}
}
UserServiceImpl2.java
package com.sin.service.impl;
import com.sin.service.UserService;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/1/3 9:12
* @createAuthor SIN
* @use
*/
@Service
@Primary
public class UserServiceImpl2 implements UserService {
@Override
public void addUser(String username) {
System.out.println("添加的数据为"+ username + "位于 userServiceImpl2");
}
}
UserServiceClient.java
package com.sin.pojo;
import com.sin.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
/**
* @createTime 2024/1/3 9:15
* @createAuthor SIN
* @use
*/
@Component
public class UserServiceClient {
private final UserService userService;
public UserServiceClient(UserService userService) {
this.userService = userService;
}
public void addUser(String username){
userService.addUser(username);
}
}
AppConfig.java
package com.sin.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
* @createTime 2024/1/2 10:56
* @createAuthor SIN
* @use
*/
@Configuration
@ComponentScan(basePackages = "com.sin") // 扫描组件
public class AppConfig {
}
AppTest.java
package com.sin.test;
import com.sin.config.AppConfig;
import com.sin.pojo.UserServiceClient;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @createTime 2024/1/3 8:41
* @createAuthor SIN
* @use
*/
public class AppTest {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserServiceClient userServiceClient = context.getBean(UserServiceClient.class);
userServiceClient.addUser("张三");
}
}
Bean的作用域和生命周期:
Bean的作用域
Spring中Bean的作用域通常有四种:
- 单例(Singleton):在整个应用程序中只创建一个Bean实例。
- 原型(Prototype):每次请求Bean时都会创建一个新的实例。
- 会话(Session):在Web应用程序中,每个会话创建一个Bean实例。
- 请求(Request):在Web应用程序中,每个请求创建一个Bean实例。
Spring Bean的生命周期包括以下几个阶段:
- 实例化:Spring容器根据Bean的定义,使用构造函数或者工厂方法创建Bean的实例。
- 属性赋值:Spring容器将Bean的属性值注入到Bean实例中。
- 初始化:Spring容器调用Bean的初始化方法,可以通过实现InitializingBean接口或者在配置文件中指定init-method来定义初始化方法。
- 使用:Bean处于可用状态,可以被其他对象引用。
- 销毁:Spring容器调用Bean的销毁方法,可以通过实现DisposableBean接口或者在配置文件中指定destroy-method来定义销毁方法。
BeanFactory
BeanFactory是Spring框架中的核心接口之一,Bean工厂用来管理和获取Spring Bean。它提供了一种延迟加载,懒加载的机制,只有在需要Bean的时候才会实例化和初始化。
BeanFacroty接口中常用的方法有:
方法 | 说明 |
---|---|
getBean(String name) | 根据给定的 Bean 名称获取对应的 Bean 实例 |
getBean(String name, Class requiredType) | 根据给定的 Bean 名称和类型获取对应的 Bean 实例 |
boolean containsBean(String name) | 判断容器中是否包含指定名称的 Bean |
boolean isSingleton(String name) | 判断指定名称的 Bean 是否为单例模式 |
boolean isPrototype(String name) | 判断指定名称的 Bean 是否为原型模式 |
Class<?> getType(String name) | 获取指定名称的 Bean 的类型 |
String[] getAliases(String name) | 获取指定名称的 Bean 的别名 |
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?><!-- XML声明,xml版本和编码格式 -->
<!-- spring配置文件起点 -->
<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="com.sin.pojo.User">
</bean>
</beans>
AppTest.java
package com.sin.test;
import com.sin.config.AppConfig;
import com.sin.pojo.User;
import com.sin.pojo.UserServiceClient;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @createTime 2024/1/3 8:41
* @createAuthor SIN
* @use
*/
public class AppTest {
@Test
public void test() {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("获取的bean地址:" + beanFactory.getBean("user"));
System.out.println("获取的bean地址:" + beanFactory.getBean("user", User.class));
System.out.println("容器中是否存在user Bean"+beanFactory.containsBean("user"));
System.out.println("是否为单例模式"+beanFactory.isSingleton("user"));
System.out.println("是否为原型模式"+beanFactory.isPrototype("user"));
System.out.println("获取到的类型为:"+beanFactory.getType("user"));
System.out.println("获取到的别名为:"+beanFactory.getAliases("user"));
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!