Spring Declare Beans from Static Fields

0

There are times when you may come across a need to declare a bean in spring context that points to a static field. For example, a bean expecting a static field in one of its constructor parameter.
There are two ways to declare a bean from a static field.

  1. You either use the spring provided factory bean FieldRetrievingFactoryBean or
  2. Use the custom tag <util:contant>

We will see examples of both cases.

This example uses the following frameworks:

  1. Maven 3.2.3
  2. Spring 4.1.5.RELEASE
  3. Eclipse  as the IDE, version Luna 4.4.1.

Dependencies

Add the following dependencies:

  1. spring-core
  2. spring-context
  3. spring-beans

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javarticles.spring</groupId>
	<artifactId>springListExample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>		
	</dependencies>

	<properties>
		<spring.version>3.2.3.RELEASE</spring.version>
	</properties>

</project>

Basic rules in defining the static fields

Let’s declare the bean for static field java.lang.Integer.MAX_VALUE. In the below context file, we define the maximum integer value using util:constant and FieldRetrievingFactoryBean.

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

	<util:constant static-field="java.lang.Integer.MAX_VALUE" />

	<bean id="intMaxValue"
		class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
		<property name="targetClass" value="java.lang.Integer" />
		<property name="targetField" value="MAX_VALUE" />
	</bean>
</beans>

SpringStaticFieldExample:

package com.javarticles.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringStaticFieldExample {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        try {
            Integer max = (Integer) context.getBean("java.lang.Integer.MAX_VALUE");
            System.out.println("Maximum value of integer: " + max);
        } finally {
            context.close();
        }
    }
}

Output:

Maximum value of integer: 2147483647

You have come across the property names targetClass, targetObject, targetField and staticField. Let me describe the properties for you.
In the above example, the targetClass is java.lang.Integer, targetObject would be a bean for class java.lang.Thread, the targetField would be the static field MAX_VALUE and the staticField would be the name of the static field, java.lang.Integer.MAX_VALUE.

There are a number of combinations in which you can define the static fields in spring if you are using the factory bean FieldRetrievingFactoryBean.

  1. Using target class and target field combination
  2. Using target object and target field combination
  3. Using just the static field

Few minor rules:

  1. You shouldn’t be providing both target object and target class, spring won’t be able to figure which one to use so it will throw an IllegalArgumentException.
  2. If both target object and target class are null, you should not provide target field, else spring will throw IllegalArgumentException
  3. If you are not providing target object and target class then you should simply provide the static field name

As long as it knows the target class and target field, it can derive the reference to the static field.

More examples

Let me show you more examples of defining static fields. Below example is about a training session which contains a list of topics to train on. The list of topics are injected using spring.
The topics are defined as static fields in class Topics.

Topics:

package com.javarticles.spring;

public class Topics {
    public static final String JAVA = "Java";
    public static final String SCALA = "Scala";
    public static final Language C = new Language("C");
    public enum JavaTopicsEnum {
        CORE,
        JDBC,
        CONCURRENCY
    }
}

A simple language bean.
Language:

package com.javarticles.spring;

public class Language {
    private String lang;
    public Language(String lang) {
        this.lang = lang;
    }
    public String getLang() {
        return lang;
    }
    public String toString() {
        return "LanguageBean(" + lang + ")";
    }
}

Training:

package com.javarticles.spring;

import java.util.ArrayList;
import java.util.List;

public class Training {
    private List<String> languages = new ArrayList<String>();
    private Language basicLanguage;
    
    public Training(){}
    
    public Training(Language basicLanguage){
        this.basicLanguage = basicLanguage;
    }
    
    public Language getBasicLanguage() {
        return basicLanguage;
    }

    public void setBasicLanguage(Language basicLanguage) {
        this.basicLanguage = basicLanguage;
    }

    public List<String> getLanguages() {
        return languages;
    }

    public void setLanguages(List<String> languages) {
        this.languages = languages;
    }
    
}

Let’s define the static fields in the spring context.

  1. scalaLanguage – It is defined using the built-in factory bean FieldRetrievingFactoryBean and we have specified the fully qualified field name in the staticField property
  2. JavaCore – It is defined using the special tag util:constant and static-field attribute which contains the fully qualified field name of the enum field declared within Topics class
  3. javaLanguage – It is defined using the built-in factory bean FieldRetrievingFactoryBean and properties, tagetObject and targetField
  4. training – Here we define Training bean which in turn has a list property languages built using the static fields. If you note instead of specifying the field name in the staticField property explicitly, we have set it as the bean name of FieldRetrievingFactoryBean
  5. basicTraining – Its constructor argument points to a static field

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

	<util:constant static-field="java.lang.Integer.MAX_VALUE" />

	<bean id="intMaxValue"
		class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
		<property name="targetClass" value="java.lang.Integer" />
		<property name="targetField" value="MAX_VALUE" />
	</bean>

	<bean id="scalaLanguage"
		class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
		<property name="staticField" value="com.javarticles.spring.Topics.SCALA" />
	</bean>
	
	<util:constant id="JavaCore"
		static-field="com.javarticles.spring.Topics$JavaTopicsEnum.CORE" />

	<bean id="topic" class="com.javarticles.spring.Topics" />
	<bean id="javaLanguage"
		class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
		<property name="targetObject" ref="topic" />
		<property name="targetField" value="JAVA" />
	</bean>

	<bean id="training" class="com.javarticles.spring.Training">
		<property name="languages">
			<list>
				<bean name="com.javarticles.spring.Topics.JAVA"
					class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
				<bean name="com.javarticles.spring.Topics.SCALA"
					class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean" />
			</list>
		</property>
		<property name="basicLanguage">
			<util:constant static-field="com.javarticles.spring.Topics.C" />
		</property>
	</bean>

	<bean id="basicTraining" class="com.javarticles.spring.Training">
		<constructor-arg index="0">
			<util:constant static-field="com.javarticles.spring.Topics.JAVA" />
		</constructor-arg>
	</bean>
</beans>

SpringStaticFieldExample:

package com.javarticles.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringStaticFieldExample {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "applicationContext.xml");
        try {
            Integer max = (Integer) context.getBean("java.lang.Integer.MAX_VALUE");
            System.out.println("Maximum value of integer: " + max);
            Topics.JavaTopicsEnum javaCore = (Topics.JavaTopicsEnum) context.getBean("JavaCore");
            System.out.println("JavaTopicsEnum: " + javaCore);
            String java = (String) context.getBean("javaLanguage");
            System.out.println("JavaLanguage field's value: " + java);
            System.out.println("SavaLanguage field's value: " + context.getBean("scalaLanguage"));
            Training training = (Training) context.getBean("training");
            System.out.println("Training on languages: " + training.getLanguages());
            System.out.println("Basic language: " + training.getBasicLanguage());
            Training basicTraining = (Training) context.getBean("basicTraining");
            System.out.println("Basic training: " + basicTraining.getBasicLanguage());
        } finally {
            context.close();
        }
    }
}

Output:

Maximum value of integer: 2147483647
JavaTopicsEnum: CORE
JavaLanguage field's value: Java
SavaLanguage field's value: Scala
Training on languages: [Java, Scala]
Basic language: LanguageBean(C)
Basic training: LanguageBean(Java)

Download the source code

In this article I showed you how to declare static fields in spring context. You can download the source code here: springStaticFieldExample.zip

Share.

Comments are closed.