Spring(二)容器
- IT业界
- 2025-09-13 18:45:02

思维导图
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; } 八 工厂模式FactoryBeanFactoryBean 是 Spring 框架中的一个接口,用于 封装复杂对象的创建过程。它的核心作用是将对象的初始化逻辑与配置解耦,适用于需要动态或条件化生成 Bean 的场景。
(1) FactoryBean 的作用复杂对象创建:当对象的创建需要多步配置(如读取外部文件、动态参数设置)时,可以用 FactoryBean 封装这些逻辑。
延迟初始化:只有在真正需要时才创建对象。
动态代理:生成代理对象(如 AOP 中的动态代理)。
第三方库集成:适配需要复杂初始化的第三方组件(如 MyBatis 的 SqlSessionFactory)。
(2) FactoryBean与普通Bean的区别 (3) FactoryBean 的核心方法实现 FactoryBean 接口需要重写以下三个方法:
T getObject():返回工厂创建的目标对象。
Class<?> getObjectType():返回目标对象的类型。
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
Spring(二)容器由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Spring(二)容器”