Chính xác thì Spring BeanPostProcessor hoạt động như thế nào?


94

Tôi đang học để lấy chứng chỉ Spring Core và tôi có một số nghi ngờ về cách Spring xử lý vòng đời của bean và đặc biệt là về bộ xử lý bean post .

Vì vậy, tôi có giản đồ này:

nhập mô tả hình ảnh ở đây

Điều đó khá rõ ràng đối với tôi:

Các bước sau đây diễn ra trong giai đoạn Định nghĩa Load Bean :

  • Các lớp @Configuration được xử lý và / hoặc @Components được quét và / hoặc các tệp XML được phân tích cú pháp.

  • Các định nghĩa về Bean được thêm vào BeanFactory (mỗi định nghĩa được lập chỉ mục dưới id của nó)

  • Đậu BeanFactoryPostProcessor đặc biệt được gọi ra, nó có thể sửa đổi định nghĩa của bất kỳ bean nào (ví dụ đối với các giá trị thay thế thuộc tính-placeholder).

Sau đó, các bước sau sẽ diễn ra trong giai đoạn tạo hạt đậu :

  • Mỗi bean được khởi tạo theo mặc định (được tạo theo đúng thứ tự với các phụ thuộc của nó được chèn vào).

  • Sau khi tiêm phụ thuộc, mỗi bean sẽ trải qua một giai đoạn xử lý sau, trong đó có thể xảy ra thêm cấu hình và khởi tạo.

  • Sau khi xử lý bài đăng, bean được khởi tạo hoàn toàn và sẵn sàng để sử dụng (được theo dõi bởi id của nó cho đến khi ngữ cảnh bị phá hủy)

Ok, điều này khá rõ ràng đối với tôi và tôi cũng biết rằng có hai loại bộ xử lý bean post là:

  • Khởi tạo: Khởi tạo bean nếu được hướng dẫn (tức là @PostConstruct).

  • Tất cả phần còn lại: cho phép cấu hình bổ sung và có thể chạy trước hoặc sau bước khởi tạo

Và tôi đăng slide này:

nhập mô tả hình ảnh ở đây

Vì vậy, nó rất rõ ràng đối với tôi những gì khởi tạo bộ xử lý bean post (chúng là các phương thức được chú thích với chú thích @PostContruct và được tự động gọi ngay sau các phương thức setter (vì vậy sau khi tiêm phụ thuộc) và tôi biết rằng tôi có thể sử dụng thực hiện một số lô khởi tạo (như điền vào bộ nhớ cache như trong ví dụ trước).

Nhưng chính xác thì điều gì đại diện cho bộ xử lý bài đậu khác? Ý của chúng tôi là gì khi nói rằng các bước này được thực hiện trước hoặc sau giai đoạn khởi tạo ?

Vì vậy, các bean của tôi được khởi tạo và các phụ thuộc của nó được đưa vào, do đó, giai đoạn khởi tạo sẽ hoàn thành (bằng cách thực thi phương thức chú thích @PostContruct ). Ý chúng tôi là gì khi nói rằng Bộ xử lý bài viết Bean được sử dụng trước giai đoạn khởi tạo? Có nghĩa là nó xảy ra trước khi thực thi phương thức chú thích @PostContruct ? Nó có nghĩa là nó có thể xảy ra trước khi tiêm phụ thuộc (trước đó các phương thức setter được gọi) không?

Và chính xác thì ý của chúng tôi là gì khi nói rằng nó được thực hiện sau bước khởi tạo . Nó có nghĩa là nó xảy ra sau đó việc thực thi một phương thức chú thích @PostContruct , hoặc điều gì?

Tôi có thể dễ dàng tìm ra lý do tại sao tôi cần một phương thức chú thích @PostContruct nhưng tôi không thể tìm ra một số ví dụ điển hình về loại trình xử lý bài đậu khác, bạn có thể chỉ cho tôi một số ví dụ điển hình về thời điểm được sử dụng không?


Tôi khá chắc rằng bạn không nên chia sẻ hình ảnh của các trang trình bày :)
Reg

@Reg Những hình ảnh này đến từ khóa học / bài thuyết trình chính xác nào?
Malvon

@Malvon Đây là phiên bản trước của khóa học chính thức mùa Xuân của Pivotal. VÀ BTW - Nếu bạn đang chuẩn bị cho bài kiểm tra, hãy bỏ qua bất kỳ thứ gì với XML :)
Reg

@Reg Có cách nào để mua khóa học mà không thực sự tham gia các lớp đào tạo không?
Malvon

Tôi đang tự hỏi Điều gì xảy ra trong phần màu tím đó của sơ đồ “Định nghĩa Bean của quá trình đăng”?
Akshay Hiremath

Câu trả lời:


48

Spring doc giải thích các BPP trong Tùy chỉnh đậu bằng BeanPostProcessor . Đậu BPP là một loại đậu đặc biệt được tạo ra trước bất kỳ loại đậu nào khác và tương tác với các loại đậu mới được tạo ra. Với cấu trúc này, Spring cung cấp cho bạn phương tiện để kết nối và tùy chỉnh hành vi vòng đời đơn giản bằng cách tự thực hiện BeanPostProcessor.

Có một BPP tùy chỉnh như

public class CustomBeanPostProcessor implements BeanPostProcessor {

    public CustomBeanPostProcessor() {
        System.out.println("0. Spring calls constructor");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        System.out.println(bean.getClass() + "  " + beanName);
        return bean;
    }
}

sẽ được gọi và in ra lớp và tên bean cho mỗi bean được tạo.

Để nhấn mạnh cách phương thức phù hợp với vòng đời của bean và thời điểm chính xác phương thức được gọi, hãy kiểm tra tài liệu

postProcessBeforeInitialization (Object bean, String beanName) Áp dụng BeanPostProcessor này cho cá thể bean mới đã cho trước bất kỳ lệnh gọi lại khởi tạo bean nào (như afterPropertiesSet của InitializingBean hoặc một phương thức init-tùy chỉnh).

postProcessAfterInitialization (Object bean, String beanName) Áp dụng BeanPostProcessor này cho cá thể bean mới đã cho sau bất kỳ lệnh gọi lại khởi tạo bean nào (như afterPropertiesSet của InitializingBean hoặc một phương thức init tùy chỉnh).

Điều quan trọng nữa là

Bean sẽ được điền các giá trị thuộc tính.

Đối với những gì liên quan đến mối quan hệ với @PostConstructghi chú rằng chú thích này là một cách thuận tiện để khai báo một postProcessAfterInitializationphương thức và Spring sẽ nhận ra nó khi bạn đăng ký CommonAnnotationBeanPostProcessorhoặc chỉ định <context:annotation-config />tệp cấu hình bean. Cho dù @PostConstructphương pháp sẽ thực hiện trước hoặc sau khi bất kỳ khác postProcessAfterInitializationphụ thuộc vào orderbất động sản

Bạn có thể định cấu hình nhiều phiên bản BeanPostProcessor và bạn có thể kiểm soát thứ tự mà các BeanPostProcessor này thực thi bằng cách đặt thuộc tính order.


30

Ví dụ điển hình cho bộ xử lý bean post là khi bạn muốn bọc bean gốc trong một phiên bản proxy, ví dụ: khi sử dụng @Transactionalchú thích.

Bộ xử lý bài viết bean sẽ được đưa ra phiên bản gốc của bean, nó có thể gọi bất kỳ phương thức nào trên đích, nhưng nó cũng có thể trả về cá thể bean thực tế cần được ràng buộc trong ngữ cảnh ứng dụng, có nghĩa là nó thực sự có thể trả về bất kỳ đối tượng mà nó muốn. Tình huống điển hình khi điều này hữu ích là khi bộ xử lý bài đậu kết thúc mục tiêu trong một phiên bản proxy. Tất cả các lệnh gọi trên bean bị ràng buộc trong ngữ cảnh ứng dụng sẽ đi qua proxy và proxy sau đó sẽ thực hiện một số phép thuật trước và / hoặc sau các lệnh gọi trên bean đích, ví dụ như AOP hoặc quản lý giao dịch.


6
Kudos cho một ví dụ thực tế!
raiks

nhờ việc cung cấp use-case thực tế và không chỉ là lý thuyết
Amol Aggarwal

4

Sự khác biệt là BeanPostProcessorsẽ móc vào khởi tạo ngữ cảnh sau đó gọi postProcessBeforeInitializationpostProcessAfterInitializationcho tất cả các bean đã xác định.

Nhưng @PostConstructchỉ được sử dụng cho lớp cụ thể mà bạn muốn tùy chỉnh tạo bean sau phương thức khởi tạo hoặc thiết lập.

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.