Spring框架-Spring Bean管理

文章目录

    • Spring Bean管理
      • Spring Bean
      • 配置方式:
        • 使用XML配置方式:
          • User.java
          • applicationContext.xml
          • UserTest.java
        • 使用注解配置方式:
          • @Component
          • @Service
          • @Repository
          • @Configuration
          • @Scope
          • @Value
          • @Qualifier
          • @Primary
      • Bean的作用域和生命周期:
      • BeanFactory

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



<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">
        
        <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(默认)、PrototypeRequestSession等。
@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




<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"));

    }
}

你可能感兴趣的:(Spring框架,spring,java,后端)