当前位置: 首页 > article >正文

Spring(二)容器


思维导图

Spring 核心概念
├── **核心注解**
│   ├── @Bean → 定义单例组件
│   ├── @Configuration → 配置类
│   ├── MVC 分层注解
│   │   ├── @Controller → 控制层
│   │   ├── @Service → 服务层
│   │   └── @Repository → 数据层
│   └── @Component → 通用组件
│
├── **组件扫描与导入**
│   ├── @ComponentScan → 批量扫描组件
│   └── @Import → 按需导入配置
│
├── **作用域与生命周期**
│   ├── @Scope → 控制组件作用域
│   └── @Lazy → 延迟初始化
│
└── **高级特性**
    ├── FactoryBean → 工厂模式创建对象
    └── @Conditional → 条件注册组件

一 定义组件@Bean 

在Spring框架中,@Bean 注解是一种用于定义和配置bean的方式。它通常与@Configuration注解一起使用,用来告诉Spring容器哪些方法需要被当作是创建和管理的bean。当一个方法上标记了@Bean注解时,这个方法会被Spring容器调用,并且其返回值将作为一个bean被注册到Spring的应用上下文中。

@Bean 的基本概念

  • 作用@Bean 注解可以用于任何带有返回类型的Spring管理的方法上,表明该方法将会生成一个bean并将其注册到Spring容器中。
  • 位置:它可以应用于类中的任何方法,但最常见的是在标注为@Configuration的配置类中使用。
  • 默认ID:如果未指定ID,那么bean的名称(ID)将是方法名。当然,你也可以通过@Bean("beanName")或者@Bean(name = "beanName")来明确指定bean的名称。

特点

  • 组件的创建时机:容器启动过程中就会创建组件对象
  • 对象是单实例特性:所有组件默认是单例的,每次直接从容器中拿,容器回提前创建组件。

(1)添加组件

代码实现:

package org.example.spring01.bean;

import lombok.Data;

@Data
public class Person {
    private String name;
    private int age;
    private String gender;


}

实现类

package org.example.spring01;

import org.example.spring01.bean.Person;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Spring01Application {

    public static void main(String[] args) {

        // 启动springboot应用
        ConfigurableApplicationContext run = SpringApplication.run(Spring01Application.class, args);

        // 获取容器中所有的默认组件
        for (String beanDefinitionName : run.getBeanDefinitionNames()) {
            System.out.println(" name " +beanDefinitionName);
        }

        System.out.println("run = " + run);

    }
    //给容器中注册一个自己的组件(方法名就是组件名)
    @Bean
    public Person person() {
        Person person = new Person();
        person.setAge(18);
        person.setGender("男");
        person.setName("张三");
        return person;
    }


}

(2)获取组件

代码实现

package org.example.spring01;

import org.example.spring01.bean.Dog;
import org.example.spring01.bean.Person;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;

import java.util.Map;

@SpringBootApplication
public class Spring01Application {

    public static void main(String[] args) {

        // 启动springboot应用
        ConfigurableApplicationContext ioc = SpringApplication.run(Spring01Application.class, args);
        System.out.println("run = " + ioc);

        // 获取容器中所有的默认组件
//        for (String beanDefinitionName : ioc.getBeanDefinitionNames()) {
//            System.out.println(" name " +beanDefinitionName);
//        }

        //获取容器中person组件(组件的四大特性,名字,类型,对象,作用域)

        // 1根据组件名获取组件
        Person zj = (Person) ioc.getBean("LiSi");
        System.out.println("person = " + zj);
        // 2按照组件类型获取对象
        Dog bean = ioc.getBean(Dog.class);
        System.out.println("bean = " + bean);
        // 3按照组件类型获取这种类型的所有对象
        Map<String, Person> beansOfType = ioc.getBeansOfType(Person.class);
        System.out.println("beansOfType = " + beansOfType);
        // 4按照名字和类型获取指定对象
        Person zhangSan = ioc.getBean("ZhangSan", Person.class);
        System.out.println("zhangSan = " + zhangSan);

    }

    //给容器中注册一个自己的组件(方法名就是组件名)
    @Bean("ZhangSan")
    public Person person() {
        Person person = new Person();
        person.setAge(18);
        person.setGender("男");
        person.setName("张三");
        return person;
    }

    @Bean("LiSi")
    public Person lisi() {
        Person person = new Person();
        person.setAge(18);
        person.setGender("男");
        person.setName("李四");
        return person;
    }

    @Bean("daHuang")
    public Dog daHuang() {
        Dog dog = new Dog();
        dog.setAge(18);
        dog.setGender("男");
        dog.setName("大黄");
        return dog;
    }
}

二 配置类@Configuration

(1)配置类的作用

  • 替代 XML 配置:传统 Spring 使用 XML 文件定义 Bean,而 @Configuration 允许用 Java 类实现同样的功能,更灵活且类型安全。

  • 集中管理 Bean:在配置类中,可以通过 @Bean 注解显式定义 Bean 的创建逻辑,并管理它们的依赖关系。

配置类也是容器中的组件

代码实现

package org.example.spring01.config;

import org.example.spring01.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 告诉Spring容器,这是一个配置类
@Configuration
public class PersonConfig {
    @Bean("ZhangSan")
    public Person person() {
        Person person = new Person();
        person.setAge(18);
        person.setGender("男");
        person.setName("张三");
        return person;
    }

    @Bean("LiSi")
    public Person lisi() {
        Person person = new Person();
        person.setAge(18);
        person.setGender("男");
        person.setName("李四");
        return person;
    }

}

package org.example.spring01.config;

import org.example.spring01.bean.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DogConfig {
    @Bean("daHuang")
    public Dog daHuang() {
        Dog dog = new Dog();
        dog.setAge(18);
        dog.setGender("男");
        dog.setName("大黄");
        return dog;
    }
}

三 MVC分层注解

- @Controller:

标记类作为控制器,处理HTTP请求。

- @Service:

标记服务层,处理业务逻辑。

- @Repository:

标记数据访问层,即DAO层,处理数据库操作。

默认分层注解能起作用的前提:这些组件必须在主程序所在的包及其子包结构下。

四 批量扫描@ComponentScan

(1) 默认扫描当前包及其子包

  • 在配置类上添加 @ComponentScan,不指定参数时,默认扫描 当前配置类所在包及其子包

@Configuration
@ComponentScan  // 默认扫描当前包及子包
public class AppConfig {
}

(2) 指定扫描包路径

  • 通过 basePackages 或 value 参数指定要扫描的包路径(支持多个包)。

@Configuration
@ComponentScan(basePackages = {"com.example.service", "com.example.dao"})
public class AppConfig {
}

(3) 指定扫描类所在的包

  • 通过 basePackageClasses 指定某个类所在的包作为扫描起点。

@Configuration
@ComponentScan(basePackageClasses = {UserService.class, UserDao.class})
public class AppConfig {
}

(4) 扫描指定包

五 使用第三方组件@Import

(1) 使用 @Bean 方法显式定义

    @Bean
    public CoreConstants coreConstants(){
        return new CoreConstants();
    }

(2)使用 @Import 引入其他配置类

//导入第三方组件
@Import(CoreConstants.class)

六 调整组件的作用域@Scope

(1)作用域的区别


代码实现:

//调整组件的作用域
@Scope("prototype")
// @Scope("prototype")->非单实例
// @Scope("singleton")->但实例(默认)
// @Scope("request")->每次请求单实例
// @Scope("session")->每次会话单实例

@Configuration
public class AppConfig {
    @Bean
    @Scope("prototype")
    public PrototypeBean prototypeBean() {
        return new PrototypeBean();
    }
}

// 测试代码
PrototypeBean bean1 = context.getBean(PrototypeBean.class);
PrototypeBean bean2 = context.getBean(PrototypeBean.class);
System.out.println(bean1 == bean2); // 输出 false(不同对象)

@Configuration
public class AppConfig {
    @Bean
    @Scope("singleton") // 默认可省略
    public SingletonBean singletonBean() {
        return new SingletonBean();
    }
}

// 测试代码
SingletonBean bean1 = context.getBean(SingletonBean.class);
SingletonBean bean2 = context.getBean(SingletonBean.class);
System.out.println(bean1 == bean2); // 输出 true(同一对象)

七 懒加载@Lazy

(1). @Lazy 注解的作用

  • 懒加载@Lazy 的作用是 延迟初始化,即在 第一次使用时 才创建对象,而不是在容器启动时创建。

  • 适用场景

    • 初始化耗时的对象(如数据库连接池)。

    • 不常用的对象(如某些工具类)。

  • 与作用域的关系

    • @Lazy 不会改变作用域,单例 Bean 仍然是单例,只是延迟创建。

    • 原型 Bean 仍然是原型,每次调用都会创建新实例。

代码实现:

    //默认是prototype单实例,但是加上@Lazy注解,变成懒加载,是单实例,但是延迟创建
    @Lazy
    @Bean("ZhangSan")
    public Person person() {
        Person person = new Person();
        person.setAge(18);
        person.setGender("男");
        person.setName("张三");
        return person;
    }

八 工厂模式FactoryBean

FactoryBean 是 Spring 框架中的一个接口,用于 封装复杂对象的创建过程。它的核心作用是将对象的初始化逻辑与配置解耦,适用于需要动态或条件化生成 Bean 的场景。

(1) FactoryBean 的作用

  • 复杂对象创建:当对象的创建需要多步配置(如读取外部文件、动态参数设置)时,可以用 FactoryBean 封装这些逻辑。

  • 延迟初始化:只有在真正需要时才创建对象。

  • 动态代理:生成代理对象(如 AOP 中的动态代理)。

  • 第三方库集成:适配需要复杂初始化的第三方组件(如 MyBatis 的 SqlSessionFactory)。

(2) FactoryBean与普通Bean的区别

(3) FactoryBean 的核心方法

实现 FactoryBean 接口需要重写以下三个方法:

  1. T getObject():返回工厂创建的目标对象。

  2. Class<?> getObjectType():返回目标对象的类型。

  3. boolean isSingleton():目标对象是否是单例。

代码实现:

package org.example.spring01.bean;

public class Car {


}

实现Factory:

package org.example.spring01.factory;

import org.example.spring01.bean.Car;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.stereotype.Component;

@Component
public class BYDFactory implements FactoryBean<Car> {
    // 调用此方法判断是否单例
    @Override
    public boolean isSingleton() {
        return FactoryBean.super.isSingleton();
    }

    // 调用此方法给容器中制造对象
    @Override
    public Car getObject() throws Exception {
        return new Car();
    }

    // 调用此方法返回对象类型
    @Override
    public Class<?> getObjectType() {
        return  Car.class;
    }

}

九 @Conditional


http://www.kler.cn/a/570146.html

相关文章:

  • Metasploit multi/handler 模块高级选项解析
  • 014 rocketmq角色介绍
  • 谷仓的安保
  • MySQL:MySQL的数据类型
  • 全志A133 android10 mipi屏幕调试
  • NameError: name ‘libpaddle‘ is not defined
  • 【windows driver】 开发环境简明安装教程
  • ECS单机部署Hadoop
  • CSS中table常用的独有属性
  • 【软件安装】WebStorm现在免费,但是是非商业版本
  • Machine Learning 初探
  • 火语言RPA--PDF提取表格
  • 【安装Linux on Windows with WSL】包括 VS Code 和 Git
  • 深入解析 Vue Router 的 beforeEach:功能、用法与实践指南
  • 【部署】Docker指令备忘清单(超级详细!)
  • datalist 是什么?
  • AWR microwave office 仿真学习(三)各类传输线模型学习
  • 本地部署 DeepSeek:从 Ollama 配置到 Spring Boot 集成
  • FPGA学习(一) —— 四位全加器
  • 数据挖掘工程师的技术图谱和学习路径