2010-11-10 43 views
5

Tôi đang cố gắng tiêm một bean được xác định trong ngữ cảnh mùa xuân vào một thành phần được quản lý CDI nhưng tôi không thành công. Đậu không được tiêm, thay vào đó một cá thể mới được tạo ra mỗi lần tiêm nên được thực hiện. Môi trường của tôi là Tomcat 7 với JBoss Weld.Tiêm đậu mùa xuân bằng CDI @Inject

Spring ApplicationContext là straighforward:

<beans> 
    ... 
    <bean id="testFromSpring" class="test.Test" /> 
    ... 
</bean> 

CDI quản lý đậu trông như thế này:

@javax.inject.Named("testA") 
public class TestA { 

    @javax.inject.Inject 
    private Test myTest = null; 

    ... 

    public Test getTest() { 
    return this.myTest; 
    } 

} 

Đây là tôi faces-config.xml

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" version="2.0"> 
    <application> 
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver> 
    </application> 
</faces-config> 

Tuy nhiên, khi tôi truy cập vào test thuộc tính từ bên trong trang JSF, mộtmới Ví dụđang được tạo mỗi lần truy cập xảy ra. Đây là một ví dụ đơn giản:

<html> 
    ... 
    <p>1: <h:outputText value="#{testFromSpring}" /></p> 
    <p>2: <h:outputText value="#{testA.test}" /></p> 
    ... 

tôi nhận được kết quả như sau:

1: [email protected] 
2: [email protected] 

Sau khi làm mới:

1: [email protected] 
2: [email protected] 

Tôi có thể thấy rằng đầu ra đầu tiên là đúng. Không có vấn đề làm thế nào thường xuyên làm mới trang, các testFromSpring trả về giá trị từ đậu được xác định trong bối cảnh mùa xuân. Tuy nhiên đầu ra thứ hai rõ ràng cho thấy rằng mỗi lần phương thức getTest trên các thành phần test được gọi, một cá thể Test mới được tạo và được tiêm thay vì sử dụng cá thể từ ngữ cảnh mùa xuân như tôi mong đợi.

Vì vậy, lý do của hành vi này là gì?

Làm cách nào để có thể chèn hạt từ ngữ cảnh mùa xuân vào bean được quản lý CDI?

Tôi cũng đã cố gắng sử dụng một vòng loại bằng cách sử dụng tên định nghĩa trong bối cảnh mùa xuân, nhưng bây giờ một ngoại lệ được ném cho thấy, rằng đậu không thể được tìm thấy:

org.jboss.weld.exceptions.DeploymentException: WELD-001408 Injection point has unsatisfied dependencies. Injection point: field test.TestA.myTest; Qualifiers: [@javax.inject.Named(value=testFromSpring)] 

cho mã

@javax.inject.Named("testA") 
public class TestA { 

    @javax.inject.Inject 
    @javax.inject.Named("testFromSpring") 
    private Test myTest = null; 
+0

Điều này có thể thiếu cà phê ở đây, nhưng tại sao lại tiêm một thành viên riêng tư của lớp học của bạn (đã được đặt thành không). Nó sẽ không đơn giản hơn để cung cấp myTest như một phần của hàm tạo của TestA (ví dụ: Constructor injection) –

+0

Việc tiêm chỉ là một ví dụ chứ không phải là điểm của câu hỏi. – perdian

Trả lời

12

Pascal là đúng mà bạn không thể tiêm một cái gì đó được quản lý bởi mùa xuân vào một hạt hàn (hoặc ngược lại).

Nhưng bạn có thể xác định nhà sản xuất có đậu mùa xuân và cung cấp cho họ để hàn. Điều này nghe có vẻ như một hack cực, btw, và tôi không nghĩ rằng bạn có nghĩa vụ phải sử dụng cả hai khuôn khổ trong một dự án. Chọn một và loại bỏ khác. Nếu không, bạn sẽ gặp phải nhiều vấn đề.

Đây là giao diện của nó.

@Qualifier 
@Retention(Runtime) 
public @interface SpringBean { 
    @NonBinding String name(); 
} 


public class SpringBeanProducer { 

    @Produces @SpringBean 
    public Object create(InjectionPoint ip) { 
     // get the name() from the annotation on the injection point 
     String springBeanName = ip.getAnnotations().... 

     //get the ServletContext from the FacesContext 
     ServletContext ctx = FacesContext.getCurrentInstance()... 

     return WebApplicationContextUtils 
       .getRequiredWebApplication(ctx).getBean(springBeanName); 
    } 
} 

Sau đó, bạn có thể có:

@Inject @SpringBean("fooBean") 
private Foo yourObject; 

T.B. Bạn có thể làm cho loại an toàn hơn ở trên. Thay vì nhận được đậu theo tên, bạn có thể nhận được, thông qua sự phản ánh, loại chung của điểm tiêm, và tìm kiếm nó trong bối cảnh mùa xuân.

+0

Bạn không thể tạo đối tượng và khớp với điểm tiêm Foo trong CDI – kaos

4

Tôi không nghĩ rằng Weld có thể tiêm một cái gì đó không được quản lý (instantiated) bởi Weld (một bean Spring trong trường hợp của bạn).

2

Ngoài ra còn có dự án JBoss Snowdrop. Tôi không biết nếu nó sẽ làm việc với JBoss Weld trên Tomcat, tài liệu chỉ mô tả trên JBoss 5, 6 và 7. Theo http://docs.jboss.org/snowdrop/2.0.0.Final/html/ch03.html#d0e618 nó sẽ tiêm đậu được khai báo trong jboss-spring.xml vào các vị trí được đánh dấu bằng @Spring thay vì @Inject. Không có kinh nghiệm bản thân mình mặc dù, YMMV.

Các vấn đề liên quan