该博客的普通读者知道我是Spring框架的大力支持者,但是我对应该使用它的方式持肯定的态度。 例如,我赞成显式对象实例化和显式组件连接,而不是自注释类,组件扫描和自动装配。



概念



尽管许多Spring开发人员都使用了这些概念,但是我的经验告诉我它们并不总是被完全理解。 一些解释是为了命令。



自注释类



自注释类是定义类如何通过Spring对类本身的注释进行实例化的类。 @Component @Controller@Service @Controller@Service @Controller@Repository是大多数Spring项目中常见的自注释类。



@Component
classMySelfAnnotatedClass{}



自注释类的主要缺点是类与Bean之间的硬耦合。 例如,不可能像显式创建那样实例化2个相同类的单例bean。 更糟糕的是,它将类也耦合到Spring框架本身。



注意, @Configuration类也被认为是自注释的。



元件扫描



需要在上下文中列出和注册自注释类。 可以明确地做到这一点:



@Configuration
classMyConfig{

    @Bean
    funmyClass()=MySelfAnnotatedClass()
}



但是,最普遍的选择是让Spring框架在项目类路径上搜索每个自注释的类,然后根据注释对它们进行注册。



@Configuration@ComponentScan
classMyConfig



自动接线



一些bean需要依赖项才能被初始化。 将依赖项连接到依赖项bean可以是:



  • 明确的:告诉哪个bean将满足依赖关系是开发人员的责任。
  • 隐式(或自动):Spring框架负责提供依赖关系。 为此,单个Bean必须符合条件。

关于第二种选择,请重新阅读我的旧帖子以了解相关问题。



但是,有时无法避免自动装配。 当豆Bean1在配置片段定义Config1取决于豆Bean2在片段定义Config2 ,唯一可能的喷射选项自动装配。



@Configuration
classConfig2{

    @Bean
    funbean2()=Bean2()
}

@Configuration
classConfig1{

    @Bean@Autowired
    funbean1(bean2:Bean2)=Bean1(bean2)
}



在以上代码段中,使用了自动装配而不使用自注释类。



重新发明轮子



本周,我发现自己在旧版非Spring Boot应用程序中重新实现了Spring Boot的执行器。



该体系结构非常简单:HTTP端点返回通过Jackson库序列化的Java对象(或它们的列表)。 每个端点可能返回不同的对象,并且每个端点都可以使用自定义序列化程序进行序列化。



我已经按照每个端点打包的方式组织了该项目(与每层打包相反),并且已经提供了多个端点。 我希望人们为其他目标做出贡献,并且我希望它尽可能简单。 特别是,它们应仅:



  1. 声明控制器
  2. 声明配置类
  3. 实例化Jackson序列化器

其余的应该由我编写的通用代码来处理。



正确使用自动接线



通过使用位于项目主程序包中的主配置类上的@ComponentScan ,可以轻松处理控制器和配置类。 但是串行器呢?



Spring能够将注册到上下文中的特定类的所有bean收集到一个列表中。 这意味着每个程序包都将独立声明其序列化程序,并且通用代码可以处理注册:



@Configuration@EnableWebMvc@ComponentScan
classWebConfiguration:WebMvcConfigurerAdapter(){

    @Autowired
    privatelateinitvarserializers:List<StdSerializer<*>> (1)

    overridefunconfigureMessageConverters(converters:MutableList<HttpMessageConverter<*>>){
        converters.add(MappingJackson2HttpMessageConverter().apply{
            objectMapper.registerModule(SimpleModule().apply{
                serializers.forEach{addSerializer(it)}
            })
        })
    }
}



  1. 魔术在这里发生。 该配置类已经编写完毕,新的程序包不需要做任何事情,序列化程序将成为列表的一部分。

这是一个这样的配置类的示例,声明一个序列化器bean:



@Configuration
classFooConfiguration{

    @Bean
    funfooSerializer()=FooSerializer()
}

classFooSerializer:StdSerializer<Foo>(Foo::class.java){
    ...
}



更好的是,如果需要将软件包进一步模块化为成熟的JAR,则此设置将以完全相同的方式工作,而无需进行任何更改。



结论



更好地了解自注释类,组件扫描和自动装配对所有Spring开发人员都是有益的。



而且,尽管它们在“标准” bean类中有很多缺点,但在配置类的范围内这样做不仅是完全可以接受的,而且甚至是一个优点。 在按功能逐包设计的项目中,它改善了模块化和去耦性。



翻译自: https://blog.frankel.ch/use-case-spring-component-scan/