添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Migrating Spring Java Applications to Azure App Service (Part 1: DataSources and Credentials) Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin) Unleash Peak Performance in Java Applications: Overview of Profile-Guided Optimization (PGO) Pull Requests and Tech Debt

Every now and then, there’s an angry post or comment bitching about how the Spring framework is full of XML, how terrible and verbose it is, and how the author would never use it because of that. Of course, that is completely crap. First, when Spring was created, XML was pretty hot. J2EE deployment descriptors (yes, that was the name at the time) was XML-based.

Anyway, it’s 2017 folks, and there are multiple ways to skin a cat. This article aims at listing the different ways a Spring application context can be configured so as to enlighten the aforementioned crowd — and stop the trolling around Spring and XML.

XML has been the first way to configure the Spring application context. Basically, one create an XML file with a dedicated namespace. It’s very straightforward:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="foo" class="ch.frankel.blog.Foo">
        <constructor-arg value="Hello world!" />
    </bean>
    <bean id="bar" class="ch.frankel.blog.Bar">
        <constructor-arg ref="bar" />
    </bean>
</beans>

The next step is to create the application context, using dedicated classes:

ApplicationContext ctx = new ClassPathXmlApplicationContext("ch/frankel/blog/context.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("/opt/app/context.xml");
ApplicationContext ctx = new GenericXmlApplicationContext("classpath:ch/frankel/blog/context.xml");

XML’s declarative nature enforces simplicity at the cost of extra verbosity. It’s orthogonal to the code — it’s completely independent. Before the coming of JavaConfig, I still favored XML over self-annotated classes.

Self-Annotated Classes

As for every new future/technology, when Java 5 introduced annotations, there was a rush to use them. In essence, a self-annotated class will be auto-magically registered into the application context.

To achieve that, Spring provides the @Component annotation. However, to improve semantics, there are also dedicated annotations to differentiate between the 3 standard layers of the layered architecture principle:

  • @Controller
  • @Service
  • @Repository
  • This is also quite straightforward:

    @Component
    public class Foo {
        public Foo(@Value("Hello world!") String value) { 
    @Component
    public class Bar {
        @Autowired
        public Bar(Foo foo) { 
    

    To scan for self-annotated classes, a dedicated application context is necessary:

    ApplicationContext ctx = new AnnotationConfigApplicationContext("ch.frankel.blog");

    Self-annotated classes are quite easy to use, but there are some downsides:

  • A self-annotated class becomes dependent on the Spring framework. For a framework based on dependency injection, that’s quite a problem.
  • Usage of self-annotations blurs the boundary between the class and the bean. As a consequence, the class cannot be registered multiple times, under different names and scopes into the context.
  • Self-annotated classes require autowiring, which has downsides on its own.
  • Java Configuration

    Given the above problems regarding self-annotated classes, the Spring framework introduced a new way to configure the context: JavaConfig. In essence, JavaConfig configuration classes replace XML file, but with compile-time safety instead of XML-schema runtime validation. This is based on two annotations @Configuration for classes, and @Bean for methods.

    The equivalent of the above XML is the following snippet:

    @Configuration
    public class JavaConfiguration {
        @Bean
        public Foo foo() {
            return new Foo("Hello world!");
        @Bean
        public Bar bar() {
            return new Bar(foo());
    

    JavaConfig classes can be scanned like self-annotated classes:

    ApplicationContext ctx = new AnnotationConfigApplicationContext("ch.frankel.blog");

    JavaConfig is the way to configure Spring application: it’s orthogonal to the code, and brings some degree of compile-time validation.

    Groovy DSL

    Spring 4 added a way to configure the context via a Groovy Domain-Specific Language. The configuration takes place in a Groovy file, with the beans element as its roots.

    beans {
        foo String, 'Hello world!'
        bar Bar, foo
    

    There’s an associated application context creator class:

    ApplicationContext ctx = new GenericGroovyApplicationContext("ch/frankel/blog/context.groovy");
    

    I’m not a Groovy developer, so I never used that option. But if you are, it makes a lot of sense.

    Kotlin DSL

    Groovy has been unceremoniously kicked out of the Pivotal portfolio some time ago. There is no correlation, Kotlin has found its way in. It’s no wonder that the upcoming release of Spring 5 provides a Kotlin DSL.

    package ch.frankel.blog
    fun beans() = beans {
        bean {
            Foo("Hello world!")
            Bar(ref())
    

    Note that while bean declaration is explicit, wiring is implicit, as in JavaConfig @Bean methods with dependencies.

    In opposition to configuration flavors mentioned above, the Kotlin DSL needs an existing context to register beans in:

    import ch.frankel.blog.beans
    fun register(ctx: GenericApplicationContext) {
        beans().invoke(ctx)
    

    I didn’t use the Kotlin DSL, except to play a bit with it for a demo, so I cannot say for sure about pros/cons.

    Conclusion

    So far, the JavaConfig alternative is my favorite: It’s orthogonal to the code and provides some degree of compile-time validation. As a Kotlin enthusiast, I’m also quite eager to try the Kotlin DSL in large projects to experience its pros and cons first-hand.