Spring tải ApplicationContext hiện tại


105

Tôi đang sử dụng Spring MVC cho ứng dụng web của mình. Đậu của tôi được ghi trong spring-servlet.xmltệp ""

Bây giờ tôi có một lớp MyClassvà tôi muốn truy cập lớp này bằng cách sử dụng Spring bean

Trong spring-servlet.xmltôi đã viết sau đây

<bean id="myClass" class="com.lynas.MyClass" />

Bây giờ tôi cần truy cập cái này bằng ApplicationContext

ApplicationContext context = ??

Vì vậy, tôi có thể làm

MyClass myClass = (MyClass) context.getBean("myClass");

Làm như thế nào??


3
@ MyClass MyClass không mong muốn, myClass sẽ thực hiện công việc!
Mannekenpix

Câu trả lời:


160

Đơn giản chỉ cần tiêm nó ..

@Autowired
private ApplicationContext appContext;

hoặc triển khai giao diện này: ApplicationContextAware


Có lẽ điều này có thể làm việc: stackoverflow.com/questions/11682858/...
gipinani

ApplicationContextProvider.javaCâu trả lời sau đây có vẻ là giải pháp đáng tin cậy nhất cho điều này.
Ionut

1
Nó trả về NULL mọi lúc. Để đề cập đến ở đây mà tôi đang làm điều này bên trong một lớp học bình thường mà không phải là một "@RestController" hay một "@Component"
shah zulkarnain

1
Theo tài liệu Spring, tốt nhất bạn nên tránh @Autowosystem do một số vấn đề. Đây là liên kết spring.io/undilities/application-context . Tùy chọn tốt nhất là đi với việc triển khai giao diện ApplicationContextAware.
Durja Arai

89

Tôi nghĩ liên kết này thể hiện cách tốt nhất để lấy ngữ cảnh ứng dụng ở bất kỳ đâu, ngay cả trong lớp không đậu. Tôi thấy nó rất hữu ích. Hy vọng nó cũng như vậy cho bạn. Dưới đây là mã trừu tượng của nó

Tạo một lớp mới ApplicationContextProvider.java

package com.java2novice.spring;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ApplicationContextProvider implements ApplicationContextAware{

    private static ApplicationContext context;

    public static ApplicationContext getApplicationContext() {
        return context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac)
            throws BeansException {
        context = ac;
    }
}

Thêm một mục nhập trong application-context.xml

<bean id="applicationContextProvider"
                        class="com.java2novice.spring.ApplicationContextProvider"/>

Trong trường hợp chú thích (thay vì application-context.xml)

@Component
public class ApplicationContextProvider implements ApplicationContextAware{
...
}

Lấy bối cảnh như thế này

TestBean tb = ApplicationContextProvider.getApplicationContext().getBean("testBean", TestBean.class);

Chúc mừng !!


1
Tôi đã viết mã tương tự như Vivek. Nhưng tôi tránh tạo ApplicationContextProvider () mới mỗi khi tôi cần gọi getBean () từ ngữ cảnh. Những gì tôi đã làm là có phương thức tĩnh ApplicationContextProvider.getApplicationContext() . Sau đó, khi đó là thời gian cần bối cảnh ứng dụng hiện tại, tôi gọi:ApplicationContextProvider appContext = ApplicationContextProvider.getApplicationContext()
Panini Luncher

1
Vâng Panini Luncher, điều đó vẫn sẽ tốt. Theo gợi ý của bạn, tôi sẽ thay đổi nó theo cách đó. :)
Vivek

4
Thêm @Componentvào ApplicationContextProvidercó thể tránh cấu hình trongaplication-context.xml
bluearrow

1
Lưu ý: getter và setter của ngữ cảnh phải được đồng bộ hóa. Bạn sẽ tránh được rất nhiều vấn đề đau đầu đặc biệt cho các bài kiểm tra đơn vị / tích hợp. Trong trường hợp của tôi, ApplicationContextProvider tương tự có ngữ cảnh cũ (từ thử nghiệm tích hợp trước đó) gây ra rất nhiều lỗi phức tạp.
Oleksandr_DJ

43

Trong trường hợp bạn cần truy cập ngữ cảnh từ bên trong HttpServlet mà bản thân nó không được Spring khởi tạo (và do đó cả @Autowire và ApplicationContextAware đều không hoạt động) ...

WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());

hoặc là

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

Đối với một số câu trả lời khác, hãy suy nghĩ kỹ trước khi thực hiện điều này:

new ClassPathXmlApplicationContext("..."); // are you sure?

... vì điều này không cung cấp cho bạn bối cảnh hiện tại, thay vào đó nó tạo ra một phiên bản khác của nó cho bạn. Điều đó có nghĩa là 1) bộ nhớ đáng kể và 2) bean không được chia sẻ giữa hai bối cảnh ứng dụng này.


SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this) - đã thực hiện công việc cho tôi trong phương thức init () của bộ lọc hành động Liferay portlet.
Igor Baiborodine

Thật tuyệt vời, processInjectionBasedOnCurrentContext đã thực hiện tất cả công việc mà tôi cần. Rất cảm ơn @Jaroslav
Jad B.

ApplicationContextAware làm việc cho tôi, khi nó được chú thích với @Component như trong dung dịch Vivek của (Tôi khởi mùa xuân bối cảnh bằng tay thông qua mở rộng AbstractContextLoaderInitializer / createRootApplicationContext)
hello_earth

Hãy cảnh báo ... SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext (this); không xảy ra ngay lập tức, vì vậy bạn không thể sử dụng nó làm dòng đầu tiên trong hàm tạo của bạn chẳng hạn.
SledgeHammer

31

Nếu bạn đang triển khai một lớp không được Spring khởi tạo, chẳng hạn như JsonDeserializer, bạn có thể sử dụng:

WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
MyClass myBean = context.getBean(MyClass.class);

8
Nó không hiệu quả với tôi. Lớp học của tôi nằm ngoài bối cảnh Mùa xuân. Tôi đã cố gắng sử dụng mã của bạn nhưng nó cho tôi một phản hồi là null . Tôi đang nói vềContextLoader.getCurrentWebApplicationContext()
R. Karlus

9

Thêm cái này vào mã của bạn

@Autowired
private ApplicationContext _applicationContext;

//Add below line in your calling method
MyClass class = (MyClass) _applicationContext.getBean("myClass");

// Or you can simply use this, put the below code in your controller data member declaration part.
@Autowired
private MyClass myClass;

Điều này sẽ chỉ đơn giản là đưa myClass vào ứng dụng của bạn


6

dựa trên câu trả lời của Vivek, nhưng tôi nghĩ những điều sau sẽ tốt hơn:

@Component("applicationContextProvider")
public class ApplicationContextProvider implements ApplicationContextAware {

    private static class AplicationContextHolder{

        private static final InnerContextResource CONTEXT_PROV = new InnerContextResource();

        private AplicationContextHolder() {
            super();
        }
    }

    private static final class InnerContextResource {

        private ApplicationContext context;

        private InnerContextResource(){
            super();
        }

        private void setContext(ApplicationContext context){
            this.context = context;
        }
    }

    public static ApplicationContext getApplicationContext() {
        return AplicationContextHolder.CONTEXT_PROV.context;
    }

    @Override
    public void setApplicationContext(ApplicationContext ac) {
        AplicationContextHolder.CONTEXT_PROV.setContext(ac);
    }
}

Việc ghi từ một phương thức thể hiện sang một trường tĩnh là một việc làm không tốt và nguy hiểm nếu nhiều trường hợp đang được thao tác.


org.springframework.core.io.ContextResourcegiao diện. Tôi sẽ đề nghị chọn tên khác cho lớp bên trong ContextResourcechỉ để tránh lộn xộn.
Alexander Radchenko

@AlexanderRadchenko Ok, tôi đã đổi thành InnerContextResource
Juan

1

Có nhiều cách để lấy ngữ cảnh ứng dụng trong ứng dụng Spring. Chúng được đưa ra dưới đây:

  1. Qua ApplicationContextAware :

    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    
    public class AppContextProvider implements ApplicationContextAware {
    
    private ApplicationContext applicationContext;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    }

Tại đây, setApplicationContext(ApplicationContext applicationContext)bạn sẽ nhận được applicationContext

  1. Qua Tự động tải :

    @Autowired
    private ApplicationContext applicationContext;

Tại đây @Autowiredtừ khóa sẽ cung cấp applicationContext.

Để biết thêm thông tin, hãy truy cập chuỗi này

Cảm ơn :)


0

Một cách khác là đưa applicationContext thông qua servlet.

Đây là một ví dụ về cách chèn các phụ thuộc khi sử dụng dịch vụ web Spring.

<servlet>
        <servlet-name>my-soap-ws</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:my-applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>5</load-on-startup>

</servlet>

Cách thay thế là thêm Ngữ cảnh ứng dụng vào web.xml của bạn như hình dưới đây

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/classes/my-another-applicationContext.xml
        classpath:my-second-context.xml
    </param-value>
</context-param>

Về cơ bản, bạn đang cố gắng nói với servlet rằng nó nên tìm kiếm các bean được xác định trong các tệp ngữ cảnh này.


0

Bước 1 : Chèn mã sau vào lớp

@Autowired
private ApplicationContext _applicationContext;

Bước 2 : Viết Getter & Setter

Bước 3 : Định nghĩa autowire = "byType" trong tệp xml trong đó bean được định nghĩa


0

Ngay cả sau khi thêm @Autowire nếu lớp của bạn không phải là Lớp RestController hoặc Lớp cấu hình, đối tượng applicationContext vẫn ở dạng null. Đã thử Tạo lớp mới với bên dưới và nó đang hoạt động tốt:

@Component
public class SpringContext implements ApplicationContextAware{

   private static ApplicationContext applicationContext;

   @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws 
     BeansException {
    this.applicationContext=applicationContext;
   }
 }

sau đó, bạn có thể triển khai một phương thức getter trong cùng một lớp theo nhu cầu của bạn như nhận tham chiếu lớp được Triển khai bằng cách:

    applicationContext.getBean(String serviceName,Interface.Class)

-11
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring-servlet.xml");

Sau đó, bạn có thể lấy bean:

MyClass myClass = (MyClass) context.getBean("myClass");

Tham khảo: springbyexample.org


25
Câu trả lời này không cung cấp cho bạn bối cảnh hiện tại , nó tạo ra một trường hợp khác.
Jaroslav Záruba
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.