文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring 注解@Bean使用方式你都知道吗?

2024-11-30 15:19

关注

@Bean是方法级注释,是XML 元素的直接类比。注解支持提供的一些属性,例如:

你可以在@Configuration或@Component类中使用@Bean注释。

声明Bean

要声明bean,可以使用@Bean注释对方法进行注释。可以使用此方法在ApplicationContext中注册bean定义,其类型指定为该方法的返回值。默认情况下,bean名与方法名相同。下面的例子展示了一个@Bean方法声明:

@Configuration
public class AppConfig {


  @Bean
  public TransferServiceImpl transferService() {
    return new TransferServiceImpl();
  }
}

前面的配置与下面的Spring XML完全等效:


  

这两个声明都使一个名为transferService的bean在ApplicationContext中可用,绑定到类型为TransferServiceImpl的对象实例,如下图所示:

transferService -> com.acme.TransferServiceImpl

你也可以使用默认方法来定义bean。这允许通过在默认方法上实现带有bean定义的接口来组合bean配置。

public interface BaseConfig {


  @Bean
  default TransferServiceImpl transferService() {
    return new TransferServiceImpl();
  }
}


@Configuration
public class AppConfig implements BaseConfig {
}

你还可以用接口(或基类)返回类型声明@Bean方法,如下例所示:

@Configuration
public class AppConfig {


  @Bean
  public TransferService transferService() {
    return new TransferServiceImpl();
  }
}

然而,这将高级类型预测的可见性限制为指定的接口类型(TransferService)。然后,只有在实例化了受影响的单例bean之后,容器才知道完整类型(TransferServiceImpl)。非惰性单例bean根据其声明顺序进行实例化,因此你可能会看到不同的类型匹配结果,这取决于另一个组件何时尝试通过非声明类型进行匹配(例如@Autowired TransferServiceImpl,它只在transferServicebean实例化后才解析)。

Bean依赖

一个@Bean注释的方法可以有任意数量的参数来描述构建该Bean所需的依赖关系。例如,如果我们的TransferService需要一个AccountRepository,我们可以用一个方法参数来实现该依赖关系,如下例所示:

@Configuration
public class AppConfig {


  @Bean
  public TransferService transferService(AccountRepository accountRepository) {
    return new TransferServiceImpl(accountRepository);
  }
}

解析机制与基于构造函数的依赖注入非常相似。

Bean生命周期

使用@Bean注释定义的任何类都支持常规的生命周期回调,并且可以使用JSR-250中的@PostConstruct和@PreDestroy注释。

也完全支持常规的Spring生命周期回调。如果bean实现InitializingBean、DisposableBean或Lifecycle,那么容器将调用它们各自的方法。

还完全支持一组标准的*Aware接口(如BeanFactoryAware、BeanNameAware、MessageSourceAware、ApplicationContextAware等)。

@Bean注释支持指定任意的初始化和销毁回调方法,就像Spring XML在Bean元素上的init方法和destroy方法属性一样,如下例所示:

public class BeanOne {


  public void init() {
    // initialization logic
  }
}


public class BeanTwo {


  public void cleanup() {
    // destruction logic
  }
}


@Configuration
public class AppConfig {


  @Bean(initMethod = "init")
  public BeanOne beanOne() {
    return new BeanOne();
  }


  @Bean(destroyMethod = "cleanup")
  public BeanTwo beanTwo() {
    return new BeanTwo();
  }
}

默认情况下,使用Java配置定义的具有公共close或shutdown方法的bean会自动使用销毁回调进行登记。如果你有一个公共的close或shutdown方法,并且不希望在容器关闭时调用它,那么可以将@Bean(destroyMethod="")添加到Bean定义中,以禁用默认(推断)模式。

public class Main {


  static class Person {
    public void close() {
      System.out.println("close") ;
    }
    public void shutdown() {
      System.out.println("shutdown") ;
    }
  }
  @Configuration
  static class AppConfig {
    @Bean
    // @Bean(destroyMethod = "") 这样就禁用了关闭的操作(close和shutdown)
    public Person person() {
      return new Person() ;
    }
  }
  
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class) ;
    context.close() ;
  }
  
}

注意:如果一个类中既有close方法又有shutdown方法,那么只有close方法生效。

以前面示例中的BeanOne为例,在构造过程中直接调用init()方法同样有效,如下面的例子所示:

@Configuration
public class AppConfig {


  @Bean
  public BeanOne beanOne() {
    BeanOne beanOne = new BeanOne();
    beanOne.init();
    return beanOne;
  }
}

当你直接在Java中工作时,你可以对对象执行任何你喜欢的操作,而不必总是依赖于容器生命周期。

Bean作用域

Spring包含@Scope注释,以便您可以指定bean的范围。

你可以指定使用@Bean注释定义的Bean应该具有特定的作用域。可以使用Bean scopes部分中指定的任何标准作用域。

默认作用域是singleton,但您可以使用@Scope注释来覆盖它,如下例所示:

@Configuration
public class MyConfiguration {


  @Bean
  @Scope("prototype")
  public Encryptor encryptor() {
    // ...
  }
}

@Scope and scoped-proxy

Spring通过作用域代理提供了一种方便的方式来处理作用域依赖。在使用XML配置时,创建这样一个代理的最简单方法是元素。在Java中配置bean时,使用@Scope注解可以为proxyMode属性提供类似的支持。默认值是ScopedProxyMode.DEFAULT,它通常表示不应该创建scoped proxy,除非在组件扫描指令级别配置了不同的DEFAULT。你可以指定
ScopedProxyMode.TARGET_CLASS ScopedProxyMode。接口或ScopedProxyMode.NO。

如果你使用Java将XML参考文档(参见“限定范围的代理”)中的限定范围代理示例移植到我们的@Bean,它类似于以下内容:

// an HTTP Session-scoped bean exposed as a proxy
@Bean
@SessionScope
public UserPreferences userPreferences() {
  return new UserPreferences();
}


@Bean
public Service userService() {
  UserService service = new SimpleUserService();
  // a reference to the proxied userPreferences bean
  service.setUserPreferences(userPreferences());
  return service;
}

自定义Bean命名

默认情况下,配置类使用@Bean方法的名称作为生成的Bean的名称。但是,可以使用name属性覆盖此功能,如以下示例所示:

@Configuration
public class AppConfig {


  @Bean("myThing")
  public Thing thing() {
    return new Thing();
  }
}

Bean别名

正如Naming Beans中所讨论的,有时需要为单个bean提供多个名称,也称为bean别名。@Bean注释的name属性接受用于此目的的String数组。以下示例显示了如何为bean设置多个别名:

@Configuration
public class AppConfig {


  @Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
  public DataSource dataSource() {
    // instantiate, configure and return DataSource bean...
  }
}

Bean描述

有时,提供一个bean的更详细的文本描述是有帮助的。当bean被公开(可能是通过JMX)用于监视目的时,这可能特别有用。

要向@Bean添加描述,可以使用@Description注释,如下例所示:

@Configuration
public class AppConfig {


  @Bean
  @Description("Provides a basic example of a bean")
  public Thing thing() {
    return new Thing();
  }
}

完毕!!!

来源:实战案例锦集内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯