@Bean 注解的方法调用多次会创建多个bean 实例吗

批量添加Bean 批量添加Bean 除了使用@Component注解,或者@Configuration+@Bean注解添加Bean,还有一种方式可以批量添加Bean,就是使用@Import注解 @Import @Import注解添加在自定义的配置类上,在注解的属性中设置一个或多个需要添加的组件的Class类即可将这些组件添加到容器中 首先我们定义三个类,并且不添加@Component注解 @Data @AllArgsConstructor @NoArgsConstructor public class Person { 阅读详情

1.缘起

在看一段基于 spring security 的鉴权代码的时候,我发现一个有趣的 Bean 声明和方法调用。在一个 @Configuration 注解的配置类中用 @Bean 注解了一个方法 tokenStore,声明了 Spring bean: tokenStore。在 Spring 中,把 @Bean 注解的方法称为工厂方法,即用于创建 Spring bean 的方法。在同一个配置类另一个方法 configure 中调用了这个工厂方法 tokenStore 来获取 TokenStore 实例。

那么这会导致系统中存在多个 TokenStore 实例吗?如果是两个实例,则一个应该是 Spring bean 实例,一个是 configure 方法中通过 tokenStroe() 方法创建的实例。代码如下:

@Configuration
public class AuthorizationConfig {

    @Bean
    public TokenStore tokenStore() {
        RedisTokenStore redis = new RedisTokenStore(connectionFactory);
        return redis;
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        /*使用oauth2的密码模式时需要配置authenticationManager*/
        endpoints.authenticationManager(authenticationManager);
        //直接调用工厂方法获取 TokenStore 实例
        endpoints.tokenStore(tokenStore())
        ...
    }
    ...
}

答案是否定的,在系统中只有一个实例,这个实例就是 spring bean。这是怎么做到的呢?继续阅读之前,可以闭上眼睛思考一下。

2.原理

通过调式代码,我们可以发现这个配置类已经被 CGLIB 代理了,这个配置类的实例类名变成了 AuthorizationConfig$$EnhancerBySpringCGLIB,如图: 

断点堆栈如图: 

 这个堆栈图从最底下向上看,配置类的 configure 方法调用本类工厂方法 tokenStore,变成了调用AuthorizationConfig$$EnhancerBySpringCGLIB 的tokenStore了,而这个调用被 ConfigurationClassEnhancer$$BeanMethodInterceptor 拦截器拦截,接着堆栈出现了我们熟悉的 Spring getBean 的调用堆栈(当 bean 不存在的时候,就会触发创建 bean)。

由此可见spring 容器通过 CGLIB 代理了配置类,调用配置类 @Bean 注解的工厂方法时,这个方法会被拦截。拦截器会通过 Spring 容器的机制去获取这个工厂方法上声明的 bean,如果这个bean 实例还不存在,Spring 容器会创建 bean 实例,而这个 bean 是通过配置类的 tokenStore 方法创建的,所以最终找到通过代理类调用到了配置类的 tokenStore 方法创建了 bean 实例。

3.机制探究

Spring 为 @Configuration 专门设计了一个 BeanFactoryPostProcessor 实现类ConfigurationClassPostProcessor,我们知道 Spring 在初始化加载 bean 的过程中,预留了 BeanFactoryPostProcessor 扩展点。这个扩展点的执行时机是在 BeanFactory 初始化之后,所有的Bean定义已经被加载,但Bean的实例还没被创建(不包括 BeanFactoryPostProcessor 实例)的时候。Spring 会在这个时候调用 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法。这个扩展点通常用于修改 bean 的定义,bean 的属性值等。

我们来看看 ConfigurationClassPostProcessor 的 postProcessBeanFactory 方法实现(省略了很多代码,只列出关键部分,可以参考 spring 5.2 版本的源代码:

/**
 * Prepare the Configuration classes for servicing bean requests at runtime
 * by replacing them with CGLIB-enhanced subclasses.
 * 通过 CGLIB 增强的子类来代替配置类来为 bean 请求提供支持
 */
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
   int factoryId = System.identityHashCode(beanFactory);
   if (this.factoriesPostProcessed.contains(factoryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
   }
   this.factoriesPostProcessed.add(factoryId);
   if (!this.registriesPostProcessed.contains(factoryId)) {
      // BeanDefinitionRegistryPostProcessor hook apparently not supported...
      // Simply call processConfigurationClasses lazily at this point then.
      processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
   }
   //配置类主要的增强逻辑
   enhanceConfigurationClasses(beanFactory);
   beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
   Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();
   for (String beanName : beanFactory.getBeanDefinitionNames()) {
      ...
      //如果配置类是 full 模式,则将配置类加入到需要增强的配置类列表中
      if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
         ...
         configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
      }
   }
   if (configBeanDefs.isEmpty()) {
      // nothing to enhance -> return immediately
      return;
   }
   
   //遍历需要增强的配置类列表,为每个配置类实现增强逻辑
   ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
   for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
      ...
      // 获取配置类的 Class 对象
      Class<?> configClass = beanDef.getBeanClass();
      // 增强实现
      Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
      if (configClass != enhancedClass) {
         ...
         //将增强后的配置类设置到 bean 定义对象中
         beanDef.setBeanClass(enhancedClass);
      }
   }
}

从上面关键代码,我们可以看出 Spring 会为符合条件的 full 模式的配置类实施增强。

注: Full 模式和 lite 模式

Spring 把 bean 分成两类:full 模式和 lite 模式。在 @Configuration 注解的配置类中声明的 bean 就是 full 模式的,其他的 spring bean,比如在 @Component 注解的类中声明的 bean 都是 lite 模式。也就是说通常只有 @Configuration 注解的配置类需要增强,这也是 @Configuration 注解和其他类型的组件注解的一个重要的区别。

下面我们接着探索 ConfigurationClassEnhancer 是如何实现增强的,关键代码如下:

public Class<?> enhance(Class<?> configClass, @Nullable ClassLoader classLoader) {
   if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
      ...
      //说明已经增强过了,直接返回
      return configClass;
   }
   Class<?> enhancedClass = createClass(newEnhancer(configClass, classLoader));
   if (logger.isTraceEnabled()) {
      logger.trace(String.format("Successfully enhanced %s; enhanced class name is: %s",
            configClass.getName(), enhancedClass.getName()));
   }
   return enhancedClass;
}

/**
 * Creates a new CGLIB {@link Enhancer} instance
 */
private Enhancer newEnhancer(Class<?> configSuperClass, @Nullable ClassLoader classLoader) {
   Enhancer enhancer = new Enhancer();
   //将配置类设置为增强结果类的父类
   enhancer.setSuperclass(configSuperClass);
   enhancer.setInterfaces(new Class<?>[] {EnhancedConfiguration.class});
   enhancer.setUseFactory(false);
   //设置增加类的命名策略,即增加 BySpringCGLIB,可以看前面调试贴图中的类名
   enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
   enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
   //设置回调(拦截器)过滤器,就是说当配置类方法被调用的时候,会先执行符合过滤器条件的拦截器逻辑
   enhancer.setCallbackFilter(CALLBACK_FILTER);
   enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
   return enhancer;
}

/**
 * Uses enhancer to generate a subclass of superclass,
 * ensuring that callbacks are registered for the new subclass.
 */
private Class<?> createClass(Enhancer enhancer) {
   Class<?> subclass = enhancer.createClass();
   // 注册拦截器
   Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
   return subclass;
}

拦截器分析

增加逻辑主要是通过CGLIB enhancer 以配置类为父类创建一个代理子类,并设置了调用配置方法的时候,需要执行的拦截器。下面我们看看拦截器。

class ConfigurationClassEnhancer {

   // The callbacks to use. Note that these callbacks must be stateless.
   private static final Callback[] CALLBACKS = new Callback[] {
         new BeanMethodInterceptor(),
         new BeanFactoryAwareMethodInterceptor(),
         NoOp.INSTANCE
   };

我们再来看看 BeanMethodInterceptor 的 intercept 实现逻辑:

private static class BeanMethodInterceptor implements MethodInterceptor, ConditionalCallback {
   ...
   @Override
   @Nullable
   public Object intercept(Object enhancedConfigInstance, Method beanMethod, Object[] beanMethodArgs,
            MethodProxy cglibMethodProxy) throws Throwable {

      ...
      if (isCurrentlyInvokedFactoryMethod(beanMethod)) {

         return cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs);
      }

      return resolveBeanReference(beanMethod, beanMethodArgs, beanFactory, beanName);
   }

   private Object resolveBeanReference(Method beanMethod, Object[] beanMethodArgs,
         ConfigurableBeanFactory beanFactory, String beanName) {

      // The user (i.e. not the factory) is requesting this bean through a call to
      // the bean method, direct or indirect. The bean may have already been marked
      // as 'in creation' in certain autowiring scenarios; if so, temporarily set
      // the in-creation status to false in order to avoid an exception.
      boolean alreadyInCreation = beanFactory.isCurrentlyInCreation(beanName);
      try {
         if (alreadyInCreation) {
            beanFactory.setCurrentlyInCreation(beanName, false);
         }
         boolean useArgs = !ObjectUtils.isEmpty(beanMethodArgs);
         if (useArgs && beanFactory.isSingleton(beanName)) {
            // Stubbed null arguments just for reference purposes,
            // expecting them to be autowired for regular singleton references?
            // A safe assumption since @Bean singleton arguments cannot be optional...
            for (Object arg : beanMethodArgs) {
               if (arg == null) {
                  useArgs = false;
                  break;
               }
            }
         }
         Object beanInstance = (useArgs ? beanFactory.getBean(beanName, beanMethodArgs) :
               beanFactory.getBean(beanName));
         if (!ClassUtils.isAssignableValue(beanMethod.getReturnType(), beanInstance)) {
            // Detect package-protected NullBean instance through equals(null) check
            if (beanInstance.equals(null)) {
               if (logger.isDebugEnabled()) {
                  logger.debug(String.format("@Bean method %s.%s called as bean reference " +
                        "for type [%s] returned null bean; resolving to null value.",
                        beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
                        beanMethod.getReturnType().getName()));
               }
               beanInstance = null;
            }
            else {
               String msg = String.format("@Bean method %s.%s called as bean reference " +
                     "for type [%s] but overridden by non-compatible bean instance of type [%s].",
                     beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName(),
                     beanMethod.getReturnType().getName(), beanInstance.getClass().getName());
               try {
                  BeanDefinition beanDefinition = beanFactory.getMergedBeanDefinition(beanName);
                  msg += " Overriding bean of same name declared in: " + beanDefinition.getResourceDescription();
               }
               catch (NoSuchBeanDefinitionException ex) {
                  // Ignore - simply no detailed message then.
               }
               throw new IllegalStateException(msg);
            }
         }
         Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
         if (currentlyInvoked != null) {
            String outerBeanName = BeanAnnotationHelper.determineBeanNameFor(currentlyInvoked);
            beanFactory.registerDependentBean(beanName, outerBeanName);
         }
         return beanInstance;
      }
      finally {
         if (alreadyInCreation) {
            beanFactory.setCurrentlyInCreation(beanName, true);
         }
      }
   }

这里面和我们主题相关的就是 BeanMethodInterceptor。这个拦截器的主要逻辑就是拦截对于 @Bean 注解方法的调用,并看声明的 Spring bean 是否已经存在,如果存在则直接返回容器中的 Spring bean。否则真正的配置类的方法创建 Spring bean 实例。

总结

Spring 利用 BeanFactoryPostProcessor 扩展点, 通过 CGLIB enhancer 增强了 @Configuration 注解的配置类。重载的方式是创建了一个新的以配置类为父类增强子类。对于配置类中 @Bean 注解的方法的调用将会被拦截器拦截。拦截器的逻辑是判断声明的 Spring bean 在容器中是否已经存在,如果存在则直接返回容器中的 Spring bean。否则真正的配置类的方法创建 Spring bean 实例。

 

为什么@Configuration注解的类中,@Bean方法可以相互调用,不会产生死循环或不同的bean? 样例代码: @Configuration public class SpringTest { @Test public void test() throws IOException { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(); ... 阅读详情

相关推荐

Spring的bean默认是单例还是多例的

【Spring的bean默认是单例还是多例的】

学无止境 3280

spring

文章目录一、Spring是什么?二、Spring优点二、使用步骤1.导包2.编写xml配置文件3.调用Spring的核心容器ApplicationContext两种创建方式:1.ClassPathXmlApplicationContext2.FileSystemXmlApplicationContext获取bean三、依赖注入实现方式set注入构造器注入四、BeanBean实例化构造器实例化静态工厂实例化实例工厂实例化Bean作用域Bean生命周期总结 一、Spring是什么? 对于面试者回答什么是S.

m0_45964979的博客 805

医学图像处理实战:ABIDE数据集获取与预处理全攻略

本文详细介绍了ABIDE数据集的获取与预处理全流程,涵盖官方脚本下载、Nilearn库高效下载、数据预处理与格式转换等关键步骤。ABIDE数据集作为自闭症脑成像研究的重要资源,提供了标准化的功能磁共振成像数据,适合机器学习模型训练。文章还提供了常见问题排查与优化建议,帮助开发者高效处理医学图像数据。

weixin_29069131的博客 255

多实例Bean

多实例Bean 单例模式Bean 在Spring中,Bean默认是单例的,也就是说当我们向IOC容器中添加一个Bean,多次获取Bean,默认是同一个Bean,我们也可以显示地声明Bean为单例,使用@Scope设置属性为singleton即可 @Configuration public class MyConfiguration { @Bean @Scope("singleton") public Person person(){ return new Perso

blackball1998的博客 2343

如何从零开始写小程序

看了这篇文章,即使让我现在就从头写一个能够正常运行的小程序,也没有原本想象中的那么难了。 在本文中,我们将会以一个具体的小程序为例,带领大家从零到一完成一个小程序的开发流程,并将这个小程序上传到 FinClip.com 进行小程序提审与上架操作。 我们新建了一个叫做「HelloWorld」的小程序,FIDE 在初始化小程序项目时,会自动在项目目录中补充对应所需要的项目文件。那不妨让我们先从小程序目录下的配置文件开始,逐渐揭开小程序的面纱。 使用 FIDE 编辑小程序 1. 认识 json 文件 在小程序项目

POHOU23的博客 4395

Python+QMT量化交易实战:从零搭建你的第一个极速策略(附完整代码)

本文提供了一份详细的Python+QMT量化交易实战指南,手把手教你从零搭建一个可回测、可实盘的极速策略。内容涵盖环境配置、QMT核心机制解析、双均线策略的完整代码实现、回测优化方法以及实盘部署要点,帮助量化交易新手快速入门并掌握核心开发流程。

b9c0d的博客 1012

@Configuration、@Bean、@Component 当配置类用@Component不断调用@Bean注解的方法,会new出新对象,但是并不会覆盖一开始注入spring容器中的那个对象

当配置类用@Component不断调用@Bean注解的方法,会new出新对象,但是并不会覆盖一开始注入spring容器中的那个对象

xiaoqj123456789的博客 1638

医图论文 Arxiv‘24 | 自我先验引导的 Mamba-UNet 网络在医学图像超分辨率中的应用

作者提出了一种自我先验引导的 Mamba-UNet 网络(简称 SMamba-UNet)用于医学图像超分辨率。现有方法主要基于卷积神经网络(CNNs)或 Transformer。基于 CNN 的方法无法捕捉长距离依赖关系,而基于 Transformer 的方法由于其二阶计算复杂度,面临沉重的计算挑战。最近,状态空间模型(SSMs)尤其是 Mamba 出现了,它能够以线性计算复杂度建模长距离依赖。

小白学视觉 262

大白话讲解Spring的@bean注解

从广义上Spring注解可以分为两类: 一类注解是用于注册Bean 假如IOC容器就是一家自助餐厅,你要 比如@Component , @Repository , @ Controller , @Service , @Configration这些注解就是用于注册Bean,放进IOC容器中,一来交给spring管理方便解耦,二来还可以进行二次使用,啥是二次使用呢? 一类注解是用于使用Bean ...

宜春 3万+

tar解压报错 gzip: stdin: unexpected end of file tar: Unexpected EOF in archive

错误现象: [root@centos7-xinsz08 ~]# tar xf prometheus-2.7.2.linux-amd64.tar.gz gzip: stdin: unexpected end of file tar: 归档文件中异常的 EOF tar: 归档文件中异常的 EOF tar: Error is not recoverable: exiting now 错误原因排查 ...

互联网老辛 2万+

使用podspec创建iOS插件

概述 在WWDC 2014全球开发者大会上,苹果开放了动态库、App Extension等全新的功能,这为iOS插件化开发带来了可能。在iOS开发中,动态库是iOS提供的一种资源打包方式,可以将代码文件、头文件、资源文件和说明文档等集中在一起,并且可以在运行时进行动态加载。 目前,很多应用越做越复杂,应用程序也显得越来越臃肿。试想一下,如果将一些不常用的功能做成一个插件,然后根据用户的需求从网络中...

xiangzhihong8的专栏 992

【Spring】使用@Bean和@Import注解配置Bean,与Bean的实例化

在 Spring 中,Bean 是指由 Spring 容器管理的对象。Spring IOC 容器负责创建、配置和管理这些 Bean 对象的生命周期。Spring IOC 容器会管理应用程序中的组件,并通过依赖注入(DI)将它们组装在一起。Bean 是应用程序的核心构建块,它们通常代表应用程序中的各种对象,例如服务、数据访问对象(DAO)、控制器等。

m0_65277261的博客 3345

芒果YOLO11改进137:卷积AKConv篇,即插即用,具有任意采样形状和任意数量的参数的卷积内核

卷积AKConv篇,即插即用,具有任意采样形状和任意数量的参数的卷积内核

包括YOLOv5、YOLOv7、YOLOv8等模型改进 297

@Bean的方法中如何注入同一个@Configuration注解的类里的其他@Bean注解的bean

在看别人代码的时候,发现一个问题,简单了个例子 @Configuration public class MyConfig{ @Bean public Test1 test1() { return new Test1(); } @Bean public Test2 test2() { Test2 test2 = new Test2(); test2.setTes...

zhangustb 5432

西南科技大学数字电子技术实验七(4行串行累加器设计及FPGA实现)FPGA部分

/在k=1时输入1,并在k=0时运算。//在k=1时输入0,并在k=0时运算。//在k=1时输入1,并在k=0时运算。//在k=1时输入0,并在k=0时运算。//在k=1时输入1,并在k=0时运算。//在k=1时输入1,并在k=0时运算。//在k=1时输入0,并在k=0时运算。//在k=1时输入0,并在k=0时运算。三、程序清单(每条语句必须包括注释或在开发窗口注释后截图)四、综合、管脚分配、生成输出文件、下载(所有步骤截图)五、仿真程序清单、波形(波形截图必做,截图!.k(k),//开关。

Welcome To My6n Blog 4332

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

@bean注解和@component注解的区别_Spring 中的一些注解

这也是很久之前写的,不出所料的话今天依旧是水文章的一天,就不该年初立flag。本文打算介绍几个不太容易说出其区别,或者用途的 Spring 注解,比如@Component与@Bean的比较,@ControllerAdvice是如何处理自定义异常的等等。Spring 中的一些注解1.@Component和@Bean的区别是什么?1.作用对象不同:@Component注解...

weixin_35544490的博客 2万+

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

@Bean注解详解

@Bean注解详解 Bean 用法 @Bean表示方法产生一个由Spring管理的bean,属性的名称语义与Spring XML中的 标签配置的一样 public MyBean myBean() { // instantiate and configure MyBean obj return obj; } 当使用name属性可用时,用于确定bean名称的默认策略是使用方法的名称。 这是方便和直观的,但是如果需要显式命名,则可以在注解上使用 name 属性(或其

doublez的博客 2万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

@Bean 注解方法时,参数自主选择注入的bean

众所周知 当@Bean 注解使用在方法上面是,会被spring自动作为一个bean进行注入, bean的类型为该方法的返回类型, bean的id为方法名称 方法参数,会通过spring自动注入 问题是: 方法参数的自动注入原理 @Component public class Test{ @Bean public MyBean mytest(){ retun new MyBean(); }...

lazy_zzzzzz的博客 2万+

更简单的存取Bean方式-@Bean方法注解

类注解是添加在某个类上的,那么方法注解是添加在某个方法前的当我们使用测试类去获取Bean时,发现获取不到图一无法正确拿到Bean的原因:原因一:@Bean命名规则和不打雷注解的命名规则不同,@Bean存储的对象的命名默认是方法的名称此时改动对象名称为user1(方法名),发现还是会报错原因二:方法注解是要配合五大类注解使用注意:无法获取到对象的原因有两个,名称必须是方法名且方法注解需要配合五大类注解名称不能换成类名, 对象名等,加上五大类注解也不能成功获取到!!

chenchenchencl的博客 3255

SpringBoot注解--10--@Bean,对象注入的三种方法

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档。

时光里的博客 4083

【Spring IoC】深入解析方法注解 @Bean 搭配类注解的定义相同类单个或多个 Spring 对象的方法及注意事项和 @Bean 对 Bean 的默认命名及重命名 Bean 对象的方法及规范

【Spring IoC】深入解析方法注解 @Bean 搭配类注解的定义相同类单个或多个 Spring 对象的方法及注意事项和 @Bean 对 Bean 的默认命名及重命名 Bean 对象的方法及规范

OuO-1 的博客 834

同一个@Configuration注解的类里的@Bean注解的bean互相调用

1.准备 Configuration注解类 @Configuration public class TestConfig { @Bean public UserBean userBean(){ UserBean ub = new UserBean(); ub.setId("1"); ub.setName("test"); ...

Faon1425214630的博客 8573

@Bean注解详细介绍以及应用

@Bean是 Spring 框架中的一个注解,它用于告诉 Spring 容器,一个方法将会返回一个对象,这个对象应该被注册为 Spring 应用上下文中的一个 bean。本文详细介绍该注解以及在代码中的实际应用

weixin_56693899的博客 4072

注解详解系列 - @Bean:定义Spring管理的Bean

在今天的注解详解系列中,我们将探讨@Bean注解。@Bean是Spring提供的一个注解,用于在Java配置类中显式定义一个Spring管理的Bean。通过@Bean注解,可以灵活地定义和配置Bean,从而增强应用程序的可维护性和可测试性。@Bean注解用于定义一个Spring管理的Bean。import org} }} }} }@Bean在这个示例中,AppConfig类使用了注解,myService方法使用了@Bean。

算命de博客 2281

SpringBoot - @Bean注解详解

Spring在启动时能够把BEAN(JAVA组件)注册到ioc容器里,实现控制反转,开发人员在使用Spring开发应用时,是看不到new关键字的,所有对象都应该从容器里获得,它们的生命周期在放入容器时已经确定。@Bean注解就是把我们将要实例化的对象转化成一个Bean,放在Spring容器中,等我们使用时,就会和@Autowired、@Resource配合到使用拿到该实例。

记录并分享 1万+
上一篇: JVM分析工具概述
下一篇: Spring从入门到精通(一)—Spring概述、Spring的优势和体系结构
Java777i
博客等级 码龄4年 1粉丝 4原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值