Spring is a powerful Java programming framework that is widely used in Java applications. It provides enterprise-level services with POJOs. Spring leverages dependency injection to provide simple and effective testing capabilities. Spring Beans, dependencies, and beans required by the service are described in configuration files, which are typically in XML format. However, XML configuration files are long and difficult to use, and they can become difficult to read and control when you’re working on a large project that uses a lot of beans.

In this article I’ll show you 12 of the best tips for Spring XML configuration files. Some of them are more practical than just the best tricks. Note that other factors, such as the design of the domain model, affect XML configuration, but this article focuses more on readability and controllability of XML configuration.

1. Avoid automatic assembly

Spring can implement auto-assembly dependencies through bean class introspection, so you don’t have to explicitly describe bean properties or constructor arguments. Bean properties can be automatically assembled based on the attribute name live match type. Constructors can be automatically assembled based on the match type. You can even set up autowiring for auto-detection so that Spring will choose an appropriate mechanism for you. Look at the following example:

Spring can implement auto-assembly dependencies through bean class introspection, so you don’t have to explicitly describe bean properties or constructor arguments. Bean properties can be automatically assembled based on the attribute name live match type. Constructors can be automatically assembled based on the match type. You can even set up autowiring for auto-detection so that Spring will choose an appropriate mechanism for you. Look at the following example:

<bean id="orderService"
        class="com.lizjason.spring.OrderService"
        autowire="byName"/>
Copy the code

The property name of the OrderService class is used to match a bean instance in the container. Autoloader will silently save some type information and reduce clutter. However, since it sacrifices the intuitiveness and maintainability of this configuration, you won’t use it in real projects. Many guides and presentations tout it as a cool feature of Spring without mentioning this shortcoming. In my opinion, like Spring’s object pool, it’s a little more commercial. It may seem like it makes the XML configuration file more streamlined, but it actually adds complexity, especially if many beans are already defined in your larger project. Spring allows you to mix automatic and manual assembly, but this contradiction can make XML configuration even more confusing.

2. Using naming conventions

As with Java coding, always having clear, descriptive, and consistent naming conventions in your project is very useful for developers to understand XML configuration. In the case of bean ids, for example, you can follow the naming conventions for properties in Java classes. For example, the bean ID of OrderServiceDAO should be OrderServiceDAO. For large projects, prefix the bean ID with the package name.

3. Use simplified formats

A simplified format helps reduce redundancy because it treats attribute values and references as attributes rather than child elements. Look at the following example:

<bean id="orderService"
        class="com.lizjason.spring.OrderService">
        <property name="companyName">
            <value>lizjason</value>
        </property>
        <constructor-arg>
            <ref bean="orderDAO">
        </constructor-arg>
    </bean>
Copy the code

The above program can be rewritten in simplified format as:

<bean id="orderService"
        class="com.lizjason.spring.OrderService">
        <property name="companyName"
            value="lizjason"/>
        <constructor-arg ref="orderDAO"/>
    </bean>
Copy the code

The simplified format has been available since version 1.2, but note that the absence of this simplified format not only reduces your code input, but also makes XML configuration much cleaner. This can significantly improve readability when you have a large number of bean definitions in your configuration file.

4. Use type instead of index to solve constructor argument matching problems

When the constructor has multiple arguments of the same type, Spring only allows you to use index or value tags starting at 0. Look at the following example:

<bean id="billingService"
        class="com.lizjason.spring.BillingService">
        <constructor-arg index="0" value="lizjason"/>
        <constructor-arg index="1" value="100"/>
    </bean>
Copy the code

It is best to replace the above with the type attribute:

<bean id="billingService"
        class="com.lizjason.spring.BillingService">
        <constructor-arg type="java.lang.String"
            value="lizjason"/>
        <constructor-arg type="int" value="100"/>
    </bean>
Copy the code

Using index reduces redundancy slightly, but it is more error-prone and less readable than the Type attribute. You should use index only when there are conflicting arguments in the constructor.

5. Reuse bean definitions whenever possible

Spring provides an inheritance-like mechanism to reduce duplication of configuration information and make XML configuration easier. A child bean can inherit configuration information from its parent bean, which is essentially a template for its child beans. This is a must-have feature in large projects. All you have to do is set the abstract property of the parent bean to true and reference it in the child bean. Such as:

<bean id="abstractService" abstract="true"
        class="com.lizjason.spring.AbstractService">
        <property name="companyName"
            value="lizjason"/>
    </bean>
    <bean id="shippingService"
        parent="abstractService"
        class="com.lizjason.spring.ShippingService">
        <property name="shippedBy" value="lizjason"/>
    </bean>
Copy the code

The shippingService Bean inherits the value LizJason from abstractService Bean’s property companyName. Note that if you specify a class or factory method for your bean, the bean will default to abstract

6. Use ApplicationContext instead of import to assemble beans whenever possible

Like imports in Ant scripts, Spring’s import elements are useful for assembling modular beans, such as:

<beans>
        <import resource="billingServices.xml"/>
        <import resource="shippingServices.xml"/>
        <bean id="orderService"
            class="com.lizjason.spring.OrderService"/>
    <beans>
Copy the code

However, using ApplicationContext to configure these beans is more flexible and makes XML configuration more manageable than preloading them with imports in XML. You can pass an array of bean definitions to the ApplicationContext constructor as follows:

String[] serviceResources =
        {"orderServices.xml"."billingServices.xml"."shippingServices.xml"};
ApplicationContext orderServiceContext = new
ClassPathXmlApplicationContext(serviceResources);
Copy the code

7. Identify the bean with an ID

You can identify the bean with an ID or name. Using the ID is less readable, but it can influence the XML parser to make the bean reference valid. If id is not available due to XML IDREF constraints, you can use name as the bean’s identity. The XML IDREF constraint means that the ID must start with a letter (or a punctuation mark in XML parlance) and be followed by a letter, number, hyphen, underscore, colon or full stops. XML IDREF constraints are rarely encountered in practical applications.

8. Use dependency checking during development

You can set a value for the bean’s dependency check property instead of the default None, such as Simple, objects, or all, and the container will do the dependency validity check for you. This can be useful when all of a bean’s properties (or some catalog of properties) are explicitly set, or when autowiring is utilized.

<bean id="orderService"
        class="com.lizjason.spring.OrderService"
        dependency-check="objects">
        <property name="companyName"
            value="lizjason"/>
        <constructor-arg ref="orderDAO"/>
    </bean>
Copy the code

In this case, the container will ensure that these properties are not privitives or that collections is set for the orderService bean. It is possible to set default dependency checking for all beans, but this feature is rarely used because some bean properties do not need to be set.

9. Add a description comment to each configuration file

It is best to use descriptive ids and names in XML configuration files rather than piles of comments. In addition, it is useful to add a file description header that summarizes the beans defined in the file. Alternatively, you can add a description to the description element. Such as:

<beans>
        <description>
            This file defines billing service
            related beans and it depends on
            baseServices.xml,which provides
            service bean templates...
        </description>
        ...
    </beans>
Copy the code

One advantage of using the description element is that the tool can easily extract the description from the element.

10. Communicate changes to team members

When you modify the Java source code, make sure you change the appropriate part of the configuration file and let your team members know about it. XML configuration files are also code, and they are an important part of your program, but they are difficult to read and maintain. Most of the time, you need to look at both the XML configuration file and the Java code to see what’s going on.

11. Setter injection and constructor injection are preferred

Spring provides three types of injection: constructor injection, setter injection, and method injection. Generally we use the first two.

<bean id="orderService"
        class="com.lizjason.spring.OrderService">
        <constructor-arg ref="orderDAO"/>
    </bean>
    <bean id="billingService"
        class="com.lizjason.spring.BillingService">
        <property name="billingDAO"
            ref="billingDAO">
    </bean>
Copy the code

In this example, the orderService Bean uses constructor injection, and the BillingService Bean uses setter injection. Constructor injection ensures that beans are built correctly, but setter injection is more flexible and easier to control, especially if the class has multiple properties and some of them are optional.

12. Don’t abuse injection

As mentioned earlier, Spring’s ApplicationContext can create Java objects for you, but not all Java objects should be created by injection. For example, domain objects should not be created through ApplicationContext. Spring is an excellent framework, but for readability and manipulation, an XML-based configuration can be troublesome when defining many beans. Overusing dependency injection can make XML configuration more complex and verbose. Keep in mind that when using efficient ides such as Eclipse and IntelliJ, Java code is much easier to read, maintain, and manage than XML files

conclusion

XML is a popular configuration format for Spring. When there are a large number of bean definitions, xmL-based configuration can become tedious and difficult to use. Spring provides a wealth of configuration options. Properly used, these options can make XML configuration clearer, but others, such as autoneassembly, can reduce readability and maintainability. These tips mentioned in this article may help you create clean and readable XML configuration files.

Amos: focus on Java development technology research and knowledge sharing!

— — the END — —