2013-07-31 23 views
6

Tôi có một lớp trừu tượng mà tôi đang cố gắng sử dụng các chú thích @value để bơm giá trị từ một tập tin bất động sảnTiêm sở hữu sử dụng @value đến lớp trừu tượng

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; 
    } 
} 

Tôi nhận NullPointerException từ sharedVal không được thiết lập . Tôi đã cố gắng thêm khuôn mẫu @Component vào lớp trừu tượng và vẫn như cũ.

Tôi có thể đưa giá trị vào lớp trừu tượng theo cách này không? Nếu không làm thế nào có thể thực hiện điều này?

+1

Phân lớp con của bạn được khởi tạo như thế nào? – MattR

Trả lời

18

Tôi nghĩ rằng bạn sẽ tìm thấy sharedVal được được thiết lập, nhưng bạn đang cố gắng để sử dụng nó quá sớm trong constructor. Hàm khởi tạo đang được gọi (phải được gọi) trước khi Spring chèn giá trị bằng cách sử dụng chú thích @Value.

Thay vì xử lý các giá trị trong các nhà xây dựng, hãy thử một phương pháp @PostContruct thay vào đó, ví dụ:

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

(hoặc cách khác, thực hiện giao diện InitializingBean Spring).

+2

Các sớm nhất bạn nên chạm vào bất kỳ giá trị tiêm là trong một phương pháp sau xây dựng; trạng thái của các thuộc tính trước đó trong vòng đời là không xác định (tốt, thường là 'null' hoặc 0 để là pedantic). –

+0

Cảm ơn, đã học được điều gì đó mới mẻ hôm nay. – ltfishie

+0

Và làm cách nào tôi có thể nhận được giá trị được xác định trong tệp porperties của tôi? @Value ("$ {shared.val}") –

4

Tôi có thể đưa giá trị vào lớp trừu tượng theo cách này không?

Lớp trừu tượng không thể được khởi tạo, vì vậy không có gì có thể được đưa vào lớp trừu tượng. Thay vào đó, bạn nên tiêm giá trị vào lớp con cụ thể của nó.

Đảm bảo lớp con cụ thể của bạn được đánh dấu là mẫu hình @Component và là "quét thành phần" của Spring. @Component trên lớp trừu tượng là không cần thiết vì nó không thể được khởi tạo.


Cập nhật: Cuối cùng tôi tìm ra rằng bạn đang cố truy cập giá trị được chèn bên trong hàm tạo nhưng nhận thấy giá trị không được đặt. Đó là vì Spring sẽ tiêm giá trị sau khi bean được khởi tạo. Vì vậy, nếu không sử dụng hàm tạo, giá trị được tiêm không thể được truy cập bên trong hàm tạo. Bạn có thể sử dụng @PostContruct hoặc triển khai InitializingBean theo đề xuất của Matt.

chương trình Sau khi cấu hình XML được sử dụng:

<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"> 

Thực hiện hành động chung của bạn sử dụng sharedVal bên Parent#postConstruct()

+0

Cảm ơn. Tôi đã hy vọng có một cách để làm điều đó kể từ thông qua xml, bạn có thể tạo ra một bean là trừu tượng. Nhưng điều này có ý nghĩa, vì Spring không có cách nào để khởi tạo lớp trừu tượng, giá trị không thể được tiêm. Tôi chỉ có thể nghĩ đến việc sử dụng đối tượng Property để tải tệp thuộc tính của tôi và lấy khóa. Tôi hy vọng sẽ tránh điều này bằng cách sử dụng chú thích @Value – ltfishie

+1

Tôi nghĩ câu trả lời này là gây hiểu nhầm - Spring sẽ thực sự chèn các giá trị cho các thuộc tính được xác định trên các lớp cơ sở trừu tượng khi bạn đang sử dụng autowiring. – MattR

+0

@MattR. Vâng . Spring sẽ tiêm giá trị của các thuộc tính được định nghĩa trên lớp trừu tượng vào lớp con cụ thể nhưng không vào lớp trừu tượng vì lớp trừu tượng không thể được khởi tạo. Vui lòng cho tôi biết phần nào trong câu trả lời của tôi mà bạn cho là gây hiểu lầm. –