JavaRush /Blog Java /Random-VI /Khung mùa xuân. Giới thiệu
Marchello
Mức độ
Санкт-Петербург

Khung mùa xuân. Giới thiệu

Xuất bản trong nhóm
Xin chào! Trong khi quản trị JavaRush đang làm việc ở các cấp độ mới, tôi muốn bắt đầu một loạt bài viết đào tạo về Spring Framework. Vâng, tôi biết rằng đã có rất nhiều tài liệu về chủ đề này trên Internet, nhưng, như thực tế cho thấy, tất cả chúng đều ở cấp độ Hello World. Tôi muốn nói không phải về cách đặt chú thích một cách chính xác mà về cách tất cả hoạt động “dưới mui xe”. Bài viết dành cho những người đã làm việc với framework này bằng cách này hay cách khác và đã quen thuộc với các khái niệm cơ bản. Khung mùa xuân.  Giới thiệu - 1

Đang khởi tạo bối cảnh.

Vì vậy, hãy bắt đầu với những điều cơ bản. Theo tôi, một trong những điểm quan trọng nhất là hiểu cách thiết lập bối cảnh và khởi tạo các đậu. Như bạn đã biết, trước khi Spring bắt đầu hoạt động, nó cần được cấu hình. Vào thời xa xưa, việc này được thực hiện bằng cách sử dụng các tệp xml (trên một số dự án, chủ yếu là các dự án cũ, họ vẫn tiếp tục làm điều này cho đến ngày nay). Đây là một ví dụ nhỏ về tệp cấu hình như vậy:
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="ru.javarush.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
Nhìn chung, điều này là đủ để tạo một vài bộ điều khiển và khởi động quá trình khởi động (sẽ không thành công). Nhưng cấu hình này sẽ khiến Spring hoạt động như thế nào? Và đây là nơi mọi thứ trở nên thú vị. Để Spring hiểu được cấu hình của chúng tôi, có một tệp XmlBeanDefinitionReader. BeanDefinitionĐây là một thành phần Spring nội bộ có chức năng quét (phân tích cú pháp) xml và tạo các tệp dựa trên những gì chúng tôi đã viết ở đó . BeanDefinitionlà một đối tượng lưu trữ thông tin về đậu. Điều này bao gồm: nó (bean) sẽ được tạo từ lớp nào; phạm vi; liệu khởi tạo lười biếng có được cài đặt hay không; Có cần thiết phải khởi tạo một thuộc tính khác và các thuộc tính khác được mô tả trong xml trước đậu này không. Tất cả các nhận được BeanDefinitionđều được thêm vào HashMap, trong đó mã định danh là tên của Bean (do bạn đặt hoặc do Spring gán) và BeanDefinitionchính đối tượng đó. Sau khi mọi thứ BeanDefinitionđược tạo ra, một anh hùng mới xuất hiện trên sân khấu - BeanFactory. Đối tượng này lặp lại HashMap’es BeanDefinition, tạo các hạt dựa trên chúng và đặt chúng vào vùng chứa IoC. Trên thực tế, có một sắc thái ở đây, khi ứng dụng khởi động, IoC container sẽ chứa các Bean có phạm vi Singleton (được đặt theo mặc định), trong khi phần còn lại được tạo khi cần thiết (prototype, request, session). Và bây giờ lạc đề một chút, chúng ta hãy làm quen với một nhân vật khác.

Gặp gỡ BeanPostProcessor. (BPP)

bộ xử lý bài đậuThực tế là một Bean không nhất thiết phải là một lớp logic nghiệp vụ cho ứng dụng của bạn. Bean còn được gọi là đậu cơ sở hạ tầng. Nói tóm lại, một cơ sở hạ tầng là một lớp cấu hình các đậu logic nghiệp vụ của bạn (vâng, có quá nhiều đậu). Tôi sẽ cho bạn biết thêm về nó bên dưới, nhưng để hiểu rõ hơn một chút về cấu hình chính xác của BPP, tôi sẽ đưa ra một ví dụ. Mọi người có quen thuộc với bản tóm tắt không @Autowired? Vì vậy, bạn AutowiredAnnotationBeanPostProcessorcó trách nhiệm đảm bảo rằng tất cả các lớp của bạn được nhúng vào nhau. ý nghĩa của uknow

Hãy quay trở lại BeanFactory

Bây giờ đã biết về BPP, bạn cần làm rõ rằng khi lặp qua HashMapcác 's, BeanDefinitiontất cả các 's trước tiên được tạo và đặt riêng biệt (không phải trong vùng chứa IoC) BeanPostProcessor. Sau đó, các Bean thông thường trong logic nghiệp vụ của chúng tôi sẽ được tạo, đưa vào bộ chứa IoC và cấu hình của chúng bắt đầu sử dụng các BPP trì hoãn riêng biệt. Và đây là cách nó diễn ra, mỗi BPP có 2 phương thức:
postProcessorBeforeInitialization(Object bean, String beanName);
postProcessorAfterInitialization(Object bean, String beanName);
Lặp lại các thùng của chúng tôi hai lần. Lần đầu tiên phương thức được gọi postProcessorBeforeInitializationvà lần thứ hai phương thức được gọi postProcessorAfterInitialization. Chắc chắn câu hỏi đã được đặt ra là tại sao lại cần đến hai phương pháp, hãy để tôi giải thích. Thực tế là để xử lý một số chú thích (chẳng hạn như @Transactional, chẳng hạn), Bean của chúng tôi được thay thế bằng một lớp proxy. Để hiểu lý do tại sao điều này được thực hiện, bạn cần biết nó hoạt động như thế nào @Transactionalvà đây là cách nó hoạt động. Bạn cần nhanh chóng thêm một vài dòng mã vào phương thức được đánh dấu bằng chú thích này. Làm thế nào để làm nó? Đúng vậy, bằng cách tạo một lớp proxy, bên trong đó mã cần thiết sẽ được thêm vào phương thức được yêu cầu. Bây giờ hãy tưởng tượng tình huống này, chúng ta có một lớp:
class A {
    @Autowired
    private SomeClass someClass;

    @Transactional
    public void method() {
        // модификатор доступа обязательно public
    }
}
Lớp này có 2 chú thích @Autowired@Transactional. Cả hai chú thích đều được xử lý bởi các BPP khác nhau. Nếu nó hoạt động trước AutowiredBPPthì mọi thứ sẽ ổn, nhưng nếu không, chúng ta sẽ gặp phải vấn đề này. Thực tế là khi lớp proxy được tạo, tất cả thông tin meta sẽ bị mất. Nói cách khác, sẽ không có thông tin về chú thích @Autowiredtrong lớp proxy và do đó AutowiredBPPnó sẽ không hoạt động, điều đó có nghĩa là trường của chúng ta someClasssẽ có giá trị null, rất có thể sẽ dẫn đến NPE. Cũng cần biết rằng giữa các lệnh gọi phương thức, -method postProcessorBeforeInitializationsẽ được postProcessorAfterInitializationgọi init, nếu có. Về cơ bản, đây là hàm tạo thứ hai, nhưng điểm khác biệt là tại thời điểm này, tất cả các phần phụ thuộc của chúng ta đã được nhúng vào lớp và chúng ta có thể truy cập chúng từ initphương thức -. Vì vậy, một lần nữa thuật toán khởi tạo ngữ cảnh:
  1. XmlBeanDefinitionReaderquét tệp cấu hình xml của chúng tôi.
  2. Tạo BeanDefinitionvà đặt chúng vào HashMap.
  3. Đến BeanFactoryvà từ đây HashMapriêng biệt cộng lại tất cả các BeanPostProcessor's.
  4. Tạo BeanDefinitioncác hạt từ các và đặt chúng vào vùng chứa IoC.
  5. Ở đây các BPP đến và định cấu hình các loại đậu này bằng 2 phương pháp.
  6. Sẵn sàng.
Trên thực tế, chỉ vậy thôi, hãy viết nếu bạn thích bài viết này và liệu bạn có nên tiếp tục viết những bài hướng dẫn như vậy hay không.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION