Spring Bean的装配(下)介绍Bena的注解实现,Autowired注解说明

本文介绍了从Spring3.0开始的Bean管理注解实现。涵盖Classpath扫描与组件管理,如@Component等注解;类的自动检测与注册Bean,以及使用过滤器自定义扫描;还涉及定义Bean、作用域、代理方式等。同时讲解了@Required、@Autowired、@Qualifier、@Resource等注解的使用。

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

Bean管理的注解实现及例子

注:从Spring3.0开始,Spring JavaConfig项目提供了很多特性,包括使用java的时候不用XML定义bean,比如@Configuration,@Bean,@Import,@DependsOn

  • Classpath扫描与组件管理
    • @Component,@Reposiory,@Service,@Controller
    • @Component是一个通用注解,可用于任何bean
    • @Repository通常用于注解DAO类,即持久层
    • @Service通常用于注解Service类,即服务层
    • @Controller通常用于Controller类,即控制层(MVC)
  • 类的自动检测与注册Bean

    • Spring可以自动检测类并注册Bean到ApplicationContext中
    • @Service
       public class SimpleMovieLister{
      
           @Autowired
           public SimpleMovieLister(MovieFinder movieFinder) {
               this.movieFinder = movieFinder;
          }
    • 为了能够检测这些类并注册相应的Bean,需要下面内容

      <beans ..........>
      <context:component-scan base-package="org.example">
      </beans>
    • < context:component-scan>包含< context-annotation-config>,通常在使用前者后,不用再使用后者
    • AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor也会被包含进来
    • 使用过滤器进行自定义扫描

      • 默认情况下,类被自动发现并注册bean的条件是:使用@Component,@Repository,@Service,@Contraoller注解或者使用@Component的自定义注解
      • 可以通过过滤器修改上面的行为,如:下面例子忽略所有的@Repository注解并用“Stub”代替

        <beans>
         <context:component-scan base-package="org.example">
             <context:include-filter type="regex" expression=".*Stub.*Repository">
             <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
         </context:component-scan>
        </beans>
        
      • 还可使用use-default-filters=”false”
    • 定义Bean

      • 扫描过程中组件被自动检测,那么Bean名称是由BeanNameGenerator生成的(@Component,@Repository,@Service,@Controller都会有个name属性用于显式设置Bean Name)

        @Service("myMovieLister")
        public class SimpleMovieLister{
        //...
        }
        @Repository
        public class MovieFinderImpl implements MovieFinder{
        //...
        }
        
      • 可定义bean命名策略,实现BeanNameGenerator接口,并一定要包含一个无参数构造函数

        
        <beans>
         <context:component-scan base-package="org.example" name-generator="org.example.MyNameGenerator"/>
        </beans>
    • 作用域(Scope)

      • 通常情况下自动查找的Spring组件,其scope是singleton,Spring2。5提供了一个标识scope的注解是@Scope

        
        @Scope("prototype")
        @Repository
        public class MovieFinderImpl implements MovieFinder {
         //...
        }
      • 也可以自定义scope策略,实现ScopeMetadataResolver接口并提供一个无参构造器

        
         <beans>
             <context:component-scan base-package="org.example" scope-resolver="org.example.MyScopeResover">
         </beans>
    • 代理方式

      • 可以使用scoped-proxy属性指定代理,有三个值可选:no,interfaces,targetClass

        
        <beans>
         <context:component-scan base-package="org.example" scoped-proxy="interfaces"/>
        </beans>
    • A
  • < context:annotation-config/>

    • 通过在基于XML的Spring配置如下标签(请注意包含上下文命名空间)
    • 仅会查找在同一个applicationcontext中的bean注解
  • @Required

    • @Required注解是用于bean属性的setter方法
    • 这个注解仅仅表示,受影响的bean属性必须在配置时被填充,通过在bean定义或通过自动装配一个明确的属性值

      public class SimpleMovieLister{
      private MovieFinder movieFinder;
      
          @Required
          public void setMovieFinder(MovieFinder movieFinder){
                  this.movieFinder = movieFinder;
          }
      }
  • @Autowired

    • 可以将Autowired注解为“传统”的setter方法

      private MovieFinder movieFinder;
      @Autowired
      public void setMovieFinder(MovieFinder movieFinder){
      this.movieFInder = movieFinder;
      }
    • 可用于构造器或成员变量

      @Autowired
      private MovieCatalog movieCatalog;
      private CustomerPerferenceDao customerPerferenceDao;
      
      @Autowired
      public MovieRecommender(CustomerPerferenceDao customerPreferenceDao) {
           this.customerPreferenceDao = customerPreferenceDao;
      }
    • 默认情况下,如果因找不到合适的bean将会导致autowiring失败抛出异常,可以通过下面的方式避免

      
      public class SimpleMovieLister{
           private MovieFinder movieFinder;
           @Autowired(required = false)
           public void setMovieFInder(MovieFinder movieFinder) {
                      this.movieFinder = movieFinder;
          }
      }
    • 每个类只能有一个构造器被标记为required=true
    • @Autowired的必要属性,建议使用@Required注解
    • 可以使用@Autowired注解那些众所周知的解析依赖性接口,比如:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPubliser,and MessageSource

      
      public class MovieRecommender{
          @Autowired
          private ApplicationContext context;
          public MovieRecommender(){
          }
      }
    • 可以通过添加注解给需要该类型的数组的字段或方法,以提供ApplicationContext中的所有特定类型的bean

      
      private Set<MovieCatalog> movieCatalogs;
      @Autowired
      public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs){
          this.movieCatalogs = movieCatalogs;
      }
    • 可以用于装配key为String的Map

      
      private Map<String, MovieCatalog> movieCatalogs;
      @AutoWired
      public void setMovieCatalogs(map<String, MovieCatalog> movieCatalogs) {
          this.movieCatalogs = movieCatalogs;
      }
    • 如果希望数组有序,可以让bean实现org.springframework.core.Ordered接口或使用的@Order注解
    • @Autowired是由Spring BeanPostProcessor处理的,所以不能在自己的BeanPostProcessor或BeanFactoryPostProcessor类型应用这些注解,这些类型必须通过XML或者Spring的@Bean注解加载
  • @Qualifier

    • 按类型自动装配可能多个bean实例的情况,可以使用Spring的@Qualifier注解缩小范围(或指定唯一),也可以用于指定单独的构造器参数或方法参数

      
      public class MovieRecommender{
          @Autowired
          @Qualifier("main")
          private MovieCatalog movieCatalog;
      }
      public class MovieRecommender{
          private MovieCatalog movieCatalog;
          private CustomerPreferenceDao customerPreferenceDao;
          @Autowired
          public void prepare(@Qualifier("main")MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao){
          this.movieCatalog = movieCatalog;
          this.customerPreferenceDao = customerPreferenceDao; 
          }
      }

      这里写图片描述

    • 可用于注解集合类型变量
    • 如果通过名字进行注解注入,主要使用的不是@Autowired(即使在技术上能够通过@Qualifier指定bean的名字),替代方式时使用JSR-250@Resource注解,它是通过其独特的名称来定义来识别特定的目标(这是一个与所声明的类型是无关的匹配过程)
    • 因语义差异,集合或Map类型的bean无法通过@Autowired来注入,因为没有类型匹配到这样的bean,为这些bean使用@Resource注解,通过唯一名称引用集合或Map的bean
    • @Autowired适用于fields,constructors,multi-argument method这些允许在参数级别使用@Qualifier注解缩小范围的情况
    • @Resource是用于成员变量、只有一个参数的setter方法,所以在目标是构造器或一个多参数方法时,最好的方式是使用qualifiers
    • 定义自己的qualifier注解并使用

      @Target((ElementType.FIELD.FIELD,ElementType.PARAMETER))
      @Retention(RetentionPolicy.RUNTIME)
      @Qualifier
      public @interface Genre{
           String value();
      }   
      
      public class MovieRecommender{
          @Autowired
          @Genre("Action")
          private MovieCatalog actionCatalog;
          private MovieCatalog comedyCatalog;
          @Autowired
          public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
                  this.comedyCatalog = comedyCatalog;
          }
      } 
    • 自定义
      这里写图片描述
  • @Resource
### Spring Boot中Bean的完整生命周期 #### 创建阶段 在Spring Boot环境中,当应用程序启动并加载配置文件后,IoC容器会根据配置信息创建所需的Bean实例。此过程中,Spring利用Java反射机制来实例化类[^1]。 ```java // 假设有一个简单的Service组件被标记为@Component @Service public class MyService { public MyService() { System.out.println("MyService is created."); } } ``` #### 属性赋值阶段 一旦Bean对象成功创建出来之后,紧接着就是属性注入的过程,在这个时期内,依赖关系将会按照配置设定的方式(比如构造器注入、Setter方法注入等形式),由容器自动完成向新建立的对象里填充数据的工作[^2]。 #### 初始化前回调接口执行 如果某个特定类型的Bean实现了`InitializingBean`接口,则在此刻调用其内部定义好的`afterPropertiesSet()`方法;另外也可以通过实现`@PostConstruct`注解的方法达到相同的效果——这一步骤发生在所有必要的属性都已经被设置完毕之时,意味着此时可以安全地访问那些已经装配成功的成员变量了[^3]。 ```java import javax.annotation.PostConstruct; @Service public class MyService { @PostConstruct private void init(){ System.out.println("Initialization logic here"); } } ``` #### 使用中的状态维持 经过上述几个环节以后,现在该Bean就处于可使用的状态下,能够响应业务请求直到应用结束运行或者是显式地触发销毁流程之前一直保持这种活跃的状态。 #### 销毁准备活动 最后,在上下文关闭期间,对于实现了`DisposableBean`接口或是带有`@PreDestroy`标注函数的Beans来说,它们各自对应的清理工作会被依次调用以释放资源等操作。 ```java import javax.annotation.PreDestroy; @Service public class MyService { @PreDestroy private void destroy(){ System.out.println("Cleanup resources or other destruction activities"); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值