Spring注解配置应该怎么玩

时间:2022-07-22
本文章向大家介绍Spring注解配置应该怎么玩,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Spring Bean 的注解配置功能出现的比较早,但是开始流行却是由于SpringBoot的推动。初期只是提供几个注解简化一些配置,使用context:annotation-config来启用。随着AnnotationApplicationContext的出现,注解逐渐丰富,慢慢形成了一种 Java Config的体系,从而摆脱了XML。

优缺点

相对于XML文件,注解型的配置依赖于通过字节码元数据装配组件,而非尖括号的声明。通过在相应的类,方法或属性上使用注解的方式,直接组件类中进行配置,而不是使用xml表述bean的装配关系。

早期比如Eclipse这样的工具,在Bean的包名发生了变化的时候并不能同步更新XML中的配置。需要人工去修改包名,往往繁琐且容易被忘记。Refactor功能在XML配置中使用不方便,而在Java代码中使用却是非常方便。

注解的配置方式大部分情况下是去中心化,使用者很难去掌控全局,一开始就对整体很熟悉。不过这种情况随着@Configuration注解的出现得到一定的改观,原来的XML配置都可以无缝修改成一个类使用@Configuration修饰。

实例化和装配

AnnotationApplicationContext 的与 ClassPathXmlApplicationContext最大的不同点就是它的配置都是通过Annotation,那么它是怎么做到的呢?启动的时候直接扫描指定包名下的所有类,看看他们是不是存在指定的注解,然后再把他们解析成Spring 认识的BeanDefinition。

注解

作用

@Component

泛指组件,Spring容器会扫描该注解,并为其生成一个托管到容器的Bean

@Service

功能同@Component,更有语义性,表示Service层的组件

@Repository

功能同@Component,表示Dao层的Bean

@Controller

功能同@Component,表示Controller层的Bean

上述的注解均是可以定义一个bean,采用自动扫描的方式。在类定义的时候同样把它定义为一个bean。

//xml 配置方式
// UserService.java
public class UserService {
  .....
}

// appliationContext.xml
<bean class="xxxx.UserService" />

// 等价的 注解配置
// UserService.java@Service
public class UserService {
  .....
}

可以看到其实只是多了一个注解并不需要进行XML的配置。那么如果需要进行一些属性的注入呢?

这时候就需要一些装配Bean 的注解了。

注解

作用

@Autowired

按类型装配Bean,默认情况下必须要求依赖对象必须存在。如果想要按名称装配需要配合@Qualifier注解。

@Qualifier

表示要装配的Bean的名称,配合@Autowired。

@Resource

按名称进行装配,等同于@Autowired + @Qualifier 一起的功能。

使用的时候只需要用在属性或者的其中的Setter方法上面,不过Spring目前已经只推荐使用在Setter方法上。

// UserService.java@Service
public class UserService {
    private UserMapper userMapper;    
    @Autowired  public void setUserMapper(UserMapper userMapper){
        this.userMapper = userMapper;  
    }
}

编程式配置

在类实现上就地进行配置,用起来非常的方便。但是也会造成Bean定义非常的零散。如果需要有一些流程和顺序上的东西。要想知道全局总览性的视图。就会比较困难。大部分情况下,很多人喜欢使用XML和注解混合使用。如果你比较偏执,那么可以尝试下@Configuration@Bean来配置出一个具备跟XML一致的流程性的类。

假设,我们有一个业务比较复杂使用责任链的方式进行实现。有十几二十个步骤。

@Component
@Order(20)
public class FirstHandler implement IHandler{
  ....
}

@Component@Order(19)
public class SecondHandler implement IHandler{
  ....
}

// 省略其它类
@Component
@Order(1)
public class TwentiethHandler implement IHandler{
  ....
}

@Component
public class HandlerChain {
  private List<IHandler> handlerList;  
  @Autowired  
  public void setHandlerList(List<IHandler> handlerList){
      this.handlerList = handlerList;  
  }
}

如上述代码,如果全部使用注解也是可以实现的,但是handlerList的顺序对一个新接触系统的人非常不友好,因为没有一个地方可以告诉你,列表的顺序和所有的实现在哪里。我们可以换成@Configuration的方式,你可以认为它就是等同于一个配置文件。这里我们只需要修改HandlerChain的定义.

@Configuration
public class HandlerChainConfiguration{
    @Autowired  
    priavte FirstHandler firstHandler;  
      
    @Autowired  
    priavte FirstHandler secondHandler;    
    
    ...    
    
    @Autowired  
    priavte FirstHandler twentiethHandler;  
      
    @Bean  
    public HandlerChain handlerChain(){
        List<IHandler> handlerList = new ArrayList<>();    
        handlerList.add(firstHandler);    
        handlerList.add(secondHandler);    
        ...    
        handlerList.add(twentiethHandler);    
        HandlerChain handlerChain = new HandlerChain();    
        handlerChain.setHandlerList(handlerList);    
        return handlerChain;  
   }
}

上述代码使用了@Configuration@Bean 提供了一种可编程式的Bean定义,具备了很强的灵活性,它完全可以替代XML文件的方式。handlerChain的定义过程中所有的handler一览无余。

小结

@Component 等定义bean 的注解和@Autowired等装配bean的注解,相互配合可以解决任何场景下的bean配置。加上@Configuration@Bean 提供的可编程式的定义,为开发者提供了很大的便利,开发者完全可以脱离XML。有了这些基础再加上Java 的SPI机制,Spring Boot Starter就水到渠成了。