15

I have an abstract class in which I am trying to use the @Value annotation to inject value from a property file

public abstract class Parent {
     @Value ("${shared.val}")
     private String sharedVal;

     public Parent() {
        //perform common action using sharedVal
     }

}

@Component
public class ChildA extends Parent {
     Param a1;
     @Autowired
     public ChildA (Param a1) {
        super();
        this.a1 = a1;
     }
}

I am getting NullPointerException since sharedVal is not set. I tried adding @Component stereotype on the abstract class and still the same thing.

Can I inject value into abstract class this way? If not how can accomplish this?

4

2 回答 2

20

I think you'll find the sharedVal is being set, but you're trying to use it too soon in the constructor. The constructor is being called (must be called) before Spring injects the value using the @Value annotation.

Instead of processing the value in the constructor, try a @PostContruct method instead, eg:

@PostConstruct
void init() {
    //perform common action using sharedVal
 }

(or alternatively, implement Spring's InitializingBean interface).

于 2013-07-31T04:53:36.597 回答
5

Can I inject value into abstract class this way?

Abstract classes cannot be instantiated, so nothing can be injected into the abstract class. Instead , you should inject the value to its concrete subclass.

Make sure your concrete subclass is marked as @Component stereotype and being "component scanning" by Spring . @Component on the abstract class is not needed as it cannot be instantiated.


Update : I finally figure out that you are trying to access the injected value inside the constructor but found that the value is not set. It is because Spring will inject the value after the bean is instantiated . So if constructor injection is not used , the injected value cannot be accessed inside the constructor . You can use @PostContruct or implementing InitializingBean as suggested by Matt.

Following shows if XML configuration is used :

<context:property-placeholder location="classpath:xxxxx.properties" ignore-unresolvable="true" />


<bean id="parent" class="pkg.Parent" abstract="true" init-method="postConstruct">
    <property name="sharedVal" value="${shared.val}" />
</bean>


<bean id="child" class="pkg.ChildA" parent="parent">

Perform your common action using sharedVal inside Parent#postConstruct()

于 2013-07-31T04:07:38.190 回答