Spring-02 关于bean的作用域,生命周期,基于注解的注入,生成实例,半自动注解装配以及自动注解

本文详细介绍了Spring中bean的作用域,包括singleton和prototype,以及bean的生命周期。重点讨论了基于注解的装配,如@Autowired、@Qualifier和@Resource的使用,以及如何通过@Component、@Repository、@Service和@Controller注解生成和装配bean。同时,区分了半自动注解装配与自动注解装配的区别和实现方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring-02

1.bean作用域

bean的作用域有7种,最常用的有单例和原型
在这里插入图片描述

1.1 singleton 单例

singleton是Spring容器默认的作用域,当Bean的作用域为singleton时,Spring容器就只会存在一个共享的Bean实例。singleton作用域对于无会话状态的Bean(如Dao 组件、Service组件)来说,是最理想的选择。

 singleton 1.在容器启动只创建一个 id 为student1 bean  2.并且放置在容器中,容器管理他的生命周期
<!--
       声明让容器创建一个 Student类型的bean  id student1
      scope="singleton"  容器创建bean scope 默认的 作用域是单例singleton
      singleton 1.在容器启动只创建一个 id 为student1的 bean  2.并且放置在容器中,容器管理他的生命周期
-->
<bean class="com.yth.entity.Student" id="student1" scope="singleton">
    <property name="id" value="100"></property>
    <property name="name" value="赵四"></property>
</bean>

测试

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("scope/student.xml");
//关于singleton 单例的测试
@Test
public void Test01(){
    Student student = (Student) applicationContext.getBean("student1");
    System.out.println(student);
}
1.2 propertype 原型

当用户向容器获取bean 时,容器才创建,容器只负责创建,不负责保存维护他的生命周期

<!--
    声明让容器创建bean 作用域prototype
    prototype   1.用户向容器获取时 创建id student2对象 2.每次都创建新的对象
                3.容器只负责帮我们创建 不会放置在容器中,不会管理bean 的生命周期 ,由用户自己负责
-->
<bean class="com.yth.entity.Student" id="student2" scope="prototype">
    <property name="id" value="101"></property>
    <property name="name" value="广坤"></property>
</bean>

测试

//关于propertype 原型的测试
@Test
public void Test02(){
    Student student1 = (Student) applicationContext.getBean("student2");
    System.out.println(student1.hashCode());
    Student student2 = (Student) applicationContext.getBean("student2");
    System.out.println(student2.hashCode());
}

2.bean的生命周期

bean 的生老病死

单例的bean:随着容器的启动,bean 创建,容器并负责维护bean的生命周期

原型的bean: 容器启动时不创建bean,当用户获取时容器才创建bean,每次都是新的bean,容器部管理他的生命周期

Spring容器可以管理Bean部分作用域的生命周期。有关说明具体如下

  • singleton

Spring容器可以管理singleton作用域的Bean的生命周期,在此作用域下,Spring能够精确的知道该Bean何时被创建,何时初始化完成,以及何时被销毁。

  • prototype

prototype作用域的Bean,Spring只负责创建,当容器创建了Bean实例后,Bean的实例就交给客户端代码来管理,Spring容器将不再跟踪其生命周期。

示例:

1.在Student增加声明周期相关的方法

 /**
     * 初始化方法
     */
    public void  init(){

        System.out.println("对象初始化");
    }

    /**
     * 销毁方法
     */
    public void destroy(){
        System.out.println("对象销毁了");
    }

2.创建lifebean.xml,设置对应的方法

<!--
        init-method="init"  容器创建bean 时调用 初始化方法
        destroy-method="destroy"  当容器销毁时调用 销毁方法
       -->
    <bean class="com.yth.entity.Student" id="student1" scope="singleton"
          init-method="init" destroy-method="destroy">
        <property name="id" value="104"></property>
        <property name="name" value="赵四"></property>
    </bean>
    <!--
        声明 一个原型的bean  当用户获取时创建,容器只负责创建 不负责bean 的生命周期,由用户自己管理
        当容器销毁时 bean 的destroy 不会被容器调用
    -->
    <bean  id="student2" class="com.yth.entity.Student"
           scope="prototype" init-method="init" destroy-method="destroy">   
        <property name="id" value="105"></property>
        <property name="name" value="广坤"></property>
    </bean>

3.测试

//关于bean的生命周期
@Test
public void Test03(){
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("life\\lifeBean.xml");
    // 向容器获取原型  对象此时 触发原型的创建
    Student student1 = (Student) applicationContext.getBean("student1");
    // 显示调用容器的销毁方法  销毁前会将容器中所有的bean 先销毁, 调用bean 的destroy()
    Student student2 = (Student) applicationContext.getBean("student2");
    applicationContext.destroy();
}

3.基于Annotation的装配

基于XML的装配可能会导致XML配置文件过于臃肿,给后续的维护和升级带来一定的困难。为此,Spring提供了对Annotation(注解)技术的全面支持。

3.1 注入的注解

@Autowired:用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。

@Qualifier:与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。

@Resource:其作用与Autowired一样。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。

//    @Autowired  // 根据类型进行注入若有,多个类型的实例,需要配合   @Qualifier("studentDaoImpl2")
//    @Qualifier("studentDaoImpl2")

    @Resource()  // 默认按照注解的字段名称进行装配,  若没有找到根据类型装配,如果对应类型的实例有多个需要限定
    private StudentDao studentDao ;
3.2 生成实例的注解

@Component:用于描述Spring中的Bean,它是一个泛化的概念,仅仅表示一个组件。

@Repository:用于将数据访问层(DAO)的类标识为Spring中的Bean 。dao对象,时能访问数据库的

@Service:用于将业务层(Service)的类标识为Spring中的Bean。service对象,可以做业务处理,有事务等功能

@Controller:用于将控制层(Controller)的类标识为Spring中的Bean 。控制器对象,可以接受用户提交的参数,显示请求的处理结果。

3.3 半自动注解装配

只能进行注入,使注入的注解生效,bean的生成还需要在xml进行配置

实现是 context:annotation-config</context:annotation-config>

1.首先在容器中声明bean

2.使用对应注入的注解 注入bean

3.是注入的注解生效

<!--
        作用就是让 注入的注解生效
    -->
<context:annotation-config></context:annotation-config>

<!--1. 声明 bean-->
<bean id="studentDao1" class="com.yth.dao.impl.StudentDaoImpl"></bean>
<bean id="studentDao2" class="com.yth.dao.impl.StudentDaoImpl"></bean>

<bean id="studentService" class="com.yth.service.impl.StudentServiceImpl">
</bean>
public class StudentServiceImpl implements StudentService {
    //注入注解 注入bean
    @Autowired         //去容器中 查找bean,并设置到当前属性中  如果容器有 多个类型的bean则报错
 //  @Qualifier("studentDao1")//  @Qualifier 与@Autowired 配合 ,当根据类型找到多个时 使用  @Qualifier 按照id  或者name 查找为一个bean
  //  @Resource(name = "studentDao")// 首先按照 id 为属性名studentDao1 去容器中找到对应的bean 2.如果找不到 在按照类型去查找 如果找到多个 报错
    private StudentDao studentDao;
    public StudentDao getStudentDao() {
        return studentDao;
    }
    public void setStudentDao(StudentDao studentDao) {
        this.studentDao = studentDao;
    }
    public Student findStudentById(int id) {
        return studentDao.fingStudentById(id);
    }
}
  <!--
        作用就是让 注入的注解生效
    -->
    <context:annotation-config></context:annotation-config>

测试

public class Test02 {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("annotation\\ annotation.xml");
    //关于半自动注解装配测试
    @Test
    public void Test01(){
        StudentService studentService = applicationContext.getBean(StudentService.class);
        Student studentById = studentService.findStudentById(102);
        System.out.println(studentById);
    }
    //增加studentDao 的bean的声明,id不同的测试,再添加一个注解@Qualifier("studentDao1"),获取id为studentDao1的bean
    @Test
    public void Test02(){
      //  StudentService studentService = applicationContext.getBean(StudentService.class);
        StudentService studentService = (StudentService) applicationContext.getBean("studentService");
        Student studentById = studentService.findStudentById(102);
        System.out.println(studentById);
    }
    //@Resource(name = "studentDao1")  使用resource注解
    @Test
    public void Test03(){
        StudentService studentService = (StudentService) applicationContext.getBean("studentService");
        Student studentById = studentService.findStudentById(102);
        System.out.println(studentById);
    }
}
3.4 自动注解

context:component-scan

自动注解就是 通过注解自动的生成bean 并经行装配

实现:在xml 声明 context:component-scan 使对应包下的 注入的注解(@Autowired @Qualifie @Resource )生成bean的注解(@Component@Repository @Service @Controller)生效

实现

1.开启自动注解xml

	<!--
        开启 自动注解功能 使 注入的注解(@Autowired @Qualifie @Resource )生成bean的注解(@Component@Repository @Service @Controller)生效
    -->
     <context:component-scan base-package="com.qfedu"></context:component-scan>

2.标记需要 生成 bean 和主要注入的属性

dao

@Repository // 标记当前类是dao层
public class StudentDaoImpl implements StudentDao {
    public Student fingStudentById(int id) {
        Student student =new Student();
        student.setId(102);
        student.setName("刘能");
        return student;
    }
}

service

@Service
public class StudentServiceImpl implements StudentService {
    //注入注解 注入bean
    @Autowired         //去容器中 查找bean,并设置到当前属性中  如果容器有 多个类型的bean则报错
 //  @Qualifier("studentDao1")//  @Qualifier 与@Autowired 配合 ,当根据类型找到多个时 使用  @Qualifier 按照id  或者name 查找为一个bean
  //  @Resource(name = "studentDao")// 首先按照 id 为属性名studentDao1 去容器中找到对应的bean 2.如果找不到 在按照类型去查找 如果找到多个 报错
    private StudentDao studentDao;

    public StudentDao getStudentDao() {
        return studentDao;
    }
    public void setStudentDao(StudentDao studentDao) {
        this.studentDao = studentDao;
    }
    public Student findStudentById(int id) {
        return studentDao.fingStudentById(id);
    }
}

测试

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("autoAnnotation\\autoAnnotation.xml");

    //全自动注解的测试
    @Test
    public void Test01(){
        StudentService studentService = (StudentService) applicationContext.getBean(StudentService.class);
        Student studentById = studentService.findStudentById(102);
        System.out.println(studentById);
    }
<think>好的,我现在需要回答用户关于Spring框架中Bean的概念及其意义的问题。用户还提供了几个引用内容,我需要结合这些引用和之前对话中的信息来组织答案。 首先,用户的问题明确:“我想了解Spring框架中Bean的概念及其意义 请问spring框架中 bean 的定义和作用”。需要从定义和作用两方面展开。根据用户提供的引用[2],Bean是由Spring容器管理的对象,可以是任何Java类的实例,如数据库连接、业务逻辑类等。定义部分应该包括Bean的创建和管理由容器负责,而不是应用程序本身。同时,引用[3]展示了XML配置Bean的方式,而之前的回答提到注解如@Service和@Autowired,所以需要结合配置方式和注解方式来说明定义。 接下来是Bean的作用。引用[1]提到Spring容器管理Bean生命周期和依赖关系,实现松耦合和高内聚。这里可以结合控制反转(IoC)和依赖注入(DI)来解释作用,比如解耦、依赖管理。引用[4]和[5]讨论了Bean作用域,特别是singleton作为默认作用域,说明Bean的作用范围控制也是其重要功能。此外,之前的回答中提到的AOP、声明式事务、模板类等,可以关联到Bean在模块化、横切关注点处理中的作用。 需要确保结构清晰,分点阐述。例如,第一部分定义,第二部分作用,每个部分下再细分小点,比如定义包括容器管理、配置方式;作用包括解耦、生命周期管理、作用域控制、支持模块化等。 还要注意引用来源的正确标注,例如在提到Bean定义时引用[2],配置方式引用[3],作用域引用[4][5],容器管理引用[1]。同时,之前的回答中提到的三级缓存解决循环依赖,可以简要提及,但用户当前问题可能更关注概念,所以可能不需要深入技术细节,除非必要。 需要避免使用Markdown格式,用自然的中文口语化表达,分段落,每段不要太长。确保涵盖用户提供的引用内容,并结合之前回答中的信息,如IoC、DI、AOP等,来全面解释Bean的作用。 最后,检查是否有遗漏的重要点,比如Bean作用域类型(singleton, prototype等),虽然用户引用中主要提到singleton,但可以简要提及其他作用域以完整说明。同时,是否需要比较传统Java对象管理和Spring Bean管理的区别,以突出其意义,但用户的问题集中在定义和作用,可能不需要展开对比。 总结下来,回答的结构大致是: 1. Bean的定义 - 容器管理的对象 - 配置方式(XML、注解) 2. Bean的作用 - 解耦与依赖管理(IoC/DI) - 生命周期管理 - 作用域控制 - 支持模块化和集成(AOP、事务等) 需要确保每个部分都有引用支持,并自然融入之前的回答内容。例如,在解耦部分提到@Autowired和容器自动注入,引用[1][2],在作用域部分引用[4][5],配置方式引用[3]。 可能还需要注意术语的一致性,比如“松耦合”和“高内聚”来自引用[1],需要准确使用。同时,用户之前的回答中提到了三级缓存解决循环依赖,这在Bean的作用中可以提到,作为容器管理依赖的一个例子,说明其重要性。 现在需要将这些点组织成连贯的段落,使用口语化的表达,避免技术术语堆砌,同时确保信息准确,引用正确。</think>#### Spring框架中Bean的定义与核心作用 --- ### 一、Bean的定义 1. **容器管理的对象** **BeanSpring容器管理的Java对象实例**,可以是数据库连接、服务类、控制器等组件。与传统Java对象的区别在于,**Bean的创建、依赖注入生命周期完全由Spring IoC容器控制**[^2]。例如: ```java @Service public class UserService { /* 业务逻辑 */ } ``` 通过`@Service`注解标记的类会被Spring自动扫描并注册为Bean,无需手动`new`实例[^2]。 2. **配置方式** - **XML配置**:早期通过XML定义Bean及其依赖关系[^3]: ```xml <bean id="userDao" class="com.example.UserDaoImpl" /> <bean id="userService" class="com.example.UserService"> <property name="userDao" ref="userDao" /> </bean> ``` - **注解配置**:现代Spring Boot更常用`@Component`、`@Autowired`等注解简化配置。 --- ### 二、Bean的核心作用 1. **解耦与依赖管理** - **控制反转(IoC)**:Spring容器负责创建Bean注入依赖,开发者无需硬编码对象关系。例如,`UserService`依赖`UserRepository`时,只需声明`@Autowired`,容器会自动装配[^1]。 - **解决循环依赖**:通过三级缓存机制(提前暴露半成品Bean),避免因互相依赖导致的启动失败[^1]。 2. **生命周期管理** Spring管理Bean的完整生命周期,包括: - 实例化 → 属性注入 → 初始化(`@PostConstruct`) → 使用 → 销毁(`@PreDestroy`)[^1]。 例如,数据库连接池的初始化和释放可由容器自动处理。 3. **作用域控制** Bean作用域决定其实例的复用范围[^4][^5]: - **Singleton(默认)**:整个容器中只有一个实例,适用于无状态服务类。 - **Prototype**:每次请求创建新实例,适用于有状态对象(如用户会话)。 - **Request/Session**:Web环境中针对HTTP请求或会话的独立实例。 4. **支持模块化与扩展** - **AOP实现横切关注点**:通过Bean代理统一处理日志、事务等逻辑。例如,`@Transactional`注解基于动态代理实现声明式事务[^1]。 - **集成第三方组件**:Spring通过Bean管理整合MyBatis、RabbitMQ等框架,例如配置`DataSource` Bean实现数据库连接池化[^2]。 --- ### 三、实际意义对比 | 传统开发痛点 | Spring Bean的优势 | |------------------------|----------------------------------| | 手动管理对象依赖 | 容器自动注入,减少耦合 | | 重复创建相似对象 | Singleton作用域减少资源消耗 | | 生命周期管理复杂 | 容器统一控制初始化和销毁 | | 组件集成困难 | 标准化Bean定义简化第三方库整合 | --- #### 相关问题 1. Spring Bean的Singleton作用域是否线程安全? 2. 如何通过Java配置(而非XML)定义Bean? 3. Bean生命周期回调方法有哪些使用场景?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值