Spring Custom @Required styled annotation Example
In this tutorial we are creating and configuring our own custom spring @Required annotation type. This is as simple as creating the annotation, enabling the required bean dependency checking and registering the custom annotation with spring. Let’s see how.
Spring Custom @Required styled Annotation
First, create a custom @WeNeedThis
annotation. We are using this annotation as a replacement for the @Required
annotation. We need the same annotation signature as the original annotation. We cannot change the @Target
configuration to ElementType.FIELD
for example.
package com.memorynotfound.spring.core.required;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WeNeedThis {
}
Using the custom @Required annotation
We annotate our setter method with the @WeNeedThis
method. At the moment this annotation doesn’t do anything. We need to register this annotation as a @Required
styled annotation with the spring container.
package com.memorynotfound.spring.core.required;
public class StarWars {
private TheForce theForce;
public TheForce getTheForce() {
return theForce;
}
@WeNeedThis
public void setTheForce(TheForce theForce) {
this.theForce = theForce;
}
}
This object is required in the StarWars
class.
package com.memorynotfound.spring.core.required;
public class TheForce {
}
Registering the custom @Required annotation
The RequiredAnnotationBeanPostProcessor
is a spring bean post processor that is responsible for checking if all the bean properties with the @Required
annotations have been configured correctly. In other words, without the RequiredAnnotationBeanPostProcessor
the required annotation will not work. We can configure a custom required annotation by setting the requiredAnnotationType with the fully qualified class name of our custom annotation.
<?xml version="1.0" encoding="UTF-8"?>
<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 class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
<property name="requiredAnnotationType" value="com.memorynotfound.spring.core.required.WeNeedThis"/>
</bean>
<bean id="theForce" class="com.memorynotfound.spring.core.required.TheForce"/>
<bean id="c3po" class="com.memorynotfound.spring.core.required.StarWars">
<property name="theForce" ref="theForce"/>
</bean>
<bean id="luke" class="com.memorynotfound.spring.core.required.StarWars"/>
</beans>
Bootstrapping the application
We did not initialize all the classes with the custom @WeNeedThis
annotation, so the application will fail at startup.
package com.memorynotfound.spring.core.required;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String... args) {
ApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml");
StarWars starWars = (StarWars)context.getBean("luke");
System.out.println(starWars);
starWars = (StarWars)context.getBean("c3po");
System.out.println(starWars);
}
}
Because we didn’t initialize all the required properties, we receive the following exception.
Caused by: org.springframework.beans.factory.BeanInitializationException: Property 'theForce' is required for bean 'luke'
at org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.postProcessPropertyValues(RequiredAnnotationBeanPostProcessor.java:156)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
... 11 more