JavaRush /Blog Java /Random-VI /Một chuyến tham quan ngắn vào phần tiêm phụ thuộc hoặc "C...
Viacheslav
Mức độ

Một chuyến tham quan ngắn vào phần tiêm phụ thuộc hoặc "CDI còn gì nữa?"

Xuất bản trong nhóm
Nền tảng mà các framework phổ biến nhất hiện nay được xây dựng là tính năng chèn phụ thuộc. Tôi khuyên bạn nên xem đặc tả CDI nói gì về điều này, những khả năng cơ bản mà chúng tôi có và cách chúng tôi có thể sử dụng chúng.
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Giới thiệu

Tôi muốn dành bài đánh giá ngắn này cho một thứ như CDI. Cái này là cái gì? CDI là viết tắt của Bối cảnh và tiêm phụ thuộc. Đây là đặc tả Java EE mô tả Tính năng chèn phụ thuộc và các ngữ cảnh. Để biết thông tin, bạn có thể xem trang web http://cdi-spec.org . Vì CDI là một đặc tả (mô tả cách nó hoạt động, một tập hợp các giao diện), nên chúng ta cũng sẽ cần triển khai để sử dụng nó. Một trong những triển khai như vậy là Weld - http://weld.cdi-spec.org/ Để quản lý các phần phụ thuộc và tạo dự án, chúng tôi sẽ sử dụng Maven - https://maven.apache.org Vì vậy, chúng tôi đã cài đặt Maven, bây giờ chúng tôi sẽ hiểu nó trong thực tế, để không hiểu phần tóm tắt. Để làm điều này, chúng ta sẽ tạo một dự án bằng Maven. Hãy mở dòng lệnh (trong Windows, bạn có thể sử dụng Win+R để mở cửa sổ "Run" và thực thi cmd) và yêu cầu Maven làm mọi thứ cho chúng ta. Đối với điều này, Maven có một khái niệm gọi là nguyên mẫu: Maven Archetype .
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc
Sau đó, với các câu hỏi “ Chọn một số hoặc áp dụng bộ lọc ” và “ Chọn org.apache.maven.archetypes:maven-archetype-quickstart phiên bản ” chỉ cần nhấn Enter. Tiếp theo, nhập mã định danh dự án, còn gọi là GAV (xem Hướng dẫn quy ước đặt tên ).
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc
Sau khi tạo dự án thành công, chúng ta sẽ thấy dòng chữ “Xây dựng thành công”. Bây giờ chúng ta có thể mở dự án của mình trong IDE yêu thích của mình.

Thêm CDI vào dự án

Trong phần giới thiệu, chúng ta thấy rằng CDI có một trang web thú vị - http://www.cdi-spec.org/ . Có phần tải xuống, trong đó có bảng chứa dữ liệu chúng ta cần:
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc
Ở đây chúng ta có thể thấy cách Maven mô tả việc chúng tôi sử dụng API CDI trong dự án. API là một giao diện lập trình ứng dụng, tức là một số giao diện lập trình. Chúng tôi làm việc với giao diện mà không cần lo lắng về cái gì và cách thức hoạt động đằng sau giao diện này. API là một kho lưu trữ jar mà chúng tôi sẽ bắt đầu sử dụng trong dự án của mình, nghĩa là dự án của chúng tôi bắt đầu phụ thuộc vào jar này. Do đó, API CDI cho dự án của chúng tôi là một phần phụ thuộc. Trong Maven, một dự án được mô tả trong các tệp POM.xml ( POM - Project Object Model ). Các phần phụ thuộc được mô tả trong khối phụ thuộc mà chúng ta cần thêm một mục mới vào đó:
<dependency>
	<groupId>javax.enterprise</groupId>
	<artifactId>cdi-api</artifactId>
	<version>2.0</version>
</dependency>
Như bạn có thể nhận thấy, chúng tôi không chỉ định phạm vi với giá trị được cung cấp. Tại sao lại có sự khác biệt như vậy? Phạm vi này có nghĩa là ai đó sẽ cung cấp cho chúng ta sự phụ thuộc. Khi một ứng dụng chạy trên máy chủ Java EE, điều đó có nghĩa là máy chủ sẽ cung cấp cho ứng dụng tất cả các công nghệ JEE cần thiết. Để đơn giản hóa việc đánh giá này, chúng tôi sẽ làm việc trong môi trường Java SE, do đó không ai cung cấp cho chúng tôi phần phụ thuộc này. Bạn có thể đọc thêm về Phạm vi phụ thuộc tại đây: " Phạm vi phụ thuộc ". Được rồi, bây giờ chúng ta có khả năng làm việc với các giao diện. Nhưng chúng ta cũng cần thực hiện. Như chúng ta nhớ, chúng ta sẽ sử dụng Weld. Điều thú vị là các phụ thuộc khác nhau được đưa ra ở mọi nơi. Nhưng chúng tôi sẽ làm theo tài liệu. Vì vậy, hãy đọc " 18.4.5. Đặt đường dẫn lớp " và làm như nó nói:
<dependency>
	<groupId>org.jboss.weld.se</groupId>
	<artifactId>weld-se-core</artifactId>
	<version>3.0.5.Final</version>
</dependency>
Điều quan trọng là phiên bản dòng thứ ba của Weld hỗ trợ CDI 2.0. Vì vậy, chúng ta có thể tin tưởng vào API của phiên bản này. Bây giờ chúng ta đã sẵn sàng để viết mã.
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Đang khởi tạo vùng chứa CDI

CDI là một cơ chế. Phải có ai đó kiểm soát cơ chế này. Như chúng ta đã đọc ở trên, người quản lý như vậy là một thùng chứa. Vì vậy, chúng ta cần tạo ra nó, bản thân nó sẽ không xuất hiện trong môi trường SE. Hãy thêm phần sau vào phương thức chính của chúng tôi:
public static void main(String[] args) {
	SeContainerInitializer initializer = SeContainerInitializer.newInstance();
	initializer.addPackages(App.class.getPackage());
	SeContainer container = initializer.initialize();
}
Chúng tôi đã tạo vùng chứa CDI theo cách thủ công vì... Chúng tôi làm việc trong môi trường SE. Trong các dự án chiến đấu điển hình, mã chạy trên một máy chủ, nơi cung cấp nhiều công nghệ khác nhau cho mã. Theo đó, nếu máy chủ cung cấp CDI thì có nghĩa là máy chủ đó đã có sẵn bộ chứa CDI và chúng ta sẽ không cần thêm bất cứ thứ gì. Nhưng với mục đích của hướng dẫn này, chúng ta sẽ sử dụng môi trường SE. Ngoài ra, container ở đây, rõ ràng và dễ hiểu. Tại sao chúng ta cần một thùng chứa? Thùng bên trong chứa đậu (đậu CDI).
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Đậu CDI

Vì vậy, đậu. Thùng CDI là gì? Đây là một lớp Java tuân theo một số quy tắc. Các quy tắc này được mô tả trong đặc tả, ở chương " 2.2. Bean thuộc loại lớp nào? ". Hãy thêm một CDI Bean vào cùng gói với lớp Ứng dụng:
public class Logger {
    public void print(String message) {
        System.out.println(message);
    }
}
Bây giờ chúng ta có thể gọi hạt đậu này từ mainphương thức của mình:
Logger logger = container.select(Logger.class).get();
logger.print("Hello, World!");
Như bạn có thể thấy, chúng ta không tạo Bean bằng từ khóa new. Chúng tôi đã hỏi bộ chứa CDI: "Bộ chứa CDI. Tôi thực sự cần một phiên bản của lớp Logger, vui lòng đưa nó cho tôi." Phương pháp này được gọi là " Tra cứu phụ thuộc ", tức là tìm kiếm các phụ thuộc. Bây giờ hãy tạo một lớp mới:
public class DateSource {
    public String getDate() {
        return new Date().toString();
    }
}
Một lớp nguyên thủy trả về dạng văn bản của một ngày. Bây giờ hãy thêm đầu ra ngày vào tin nhắn:
public class Logger {
    @Inject
    private DateSource dateSource;

    public void print(String message) {
        System.out.println(dateSource.getDate() + " : " + message);
    }
}
Một chú thích @Inject thú vị đã xuất hiện. Như đã nêu trong chương " 4.1. Điểm phun " của tài liệu mối hàn cdi, bằng cách sử dụng chú thích này, chúng ta xác định Điểm phun. Trong tiếng Nga, điều này có thể được hiểu là “điểm thực hiện”. Chúng được bộ chứa CDI sử dụng để chèn các phần phụ thuộc khi khởi tạo đậu. Như bạn có thể thấy, chúng tôi không gán bất kỳ giá trị nào cho trường dateSource. Lý do cho điều này là thực tế là bộ chứa CDI cho phép bên trong các hạt CDI (chỉ những hạt mà nó tự khởi tạo, tức là nó quản lý) sử dụng “ Dependency Insert ”. Đây là một cách khác của Inversion of Control , một cách tiếp cận trong đó sự phụ thuộc được kiểm soát bởi người khác thay vì chúng ta tạo ra các đối tượng một cách rõ ràng. Việc chèn phụ thuộc có thể được thực hiện thông qua một phương thức, hàm tạo hoặc trường. Để biết thêm chi tiết, hãy xem chương đặc tả CDI " 5.5. Chèn phụ thuộc ". Quy trình xác định những gì cần được triển khai được gọi là giải pháp an toàn loại, đó là điều chúng ta cần nói đến.
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Độ phân giải tên hoặc độ phân giải Typesafe

Thông thường, một giao diện được sử dụng làm loại đối tượng sẽ được triển khai và chính bộ chứa CDI sẽ xác định nên chọn cách triển khai nào. Điều này hữu ích vì nhiều lý do mà chúng ta sẽ thảo luận. Vậy là chúng ta có một giao diện logger:
public interface Logger {
    void print(String message);
}
Anh ấy nói rằng nếu chúng tôi có một số trình ghi nhật ký, chúng tôi có thể gửi tin nhắn đến nó và nó sẽ hoàn thành nhiệm vụ của mình - nhật ký. Làm thế nào và ở đâu sẽ không được quan tâm trong trường hợp này. Bây giờ chúng ta hãy tạo một triển khai cho trình ghi nhật ký:
public class SystemOutLogger implements Logger {
    @Inject
    private DateSource dateSource;

    public void print(String message) {
        System.out.println(message);
    }
}
Như bạn có thể thấy, đây là một trình ghi nhật ký ghi vào System.out. Tuyệt vời. Bây giờ, phương thức chính của chúng ta sẽ hoạt động như trước. Logger logger = container.select(Logger.class).get(); Dòng này vẫn sẽ được logger nhận. Và điều thú vị là chúng ta chỉ cần biết giao diện và bộ chứa CDI đã nghĩ đến việc triển khai cho chúng ta. Giả sử chúng ta có cách triển khai thứ hai sẽ gửi nhật ký đến một nơi nào đó tới bộ lưu trữ từ xa:
public class NetworkLogger implements Logger {
    @Override
    public void print(String message) {
        System.out.println("Send log message to remote log system");
    }
}
Nếu bây giờ chúng ta chạy mã mà không thay đổi, chúng ta sẽ gặp lỗi, bởi vì Bộ chứa CDI nhìn thấy hai cách triển khai giao diện và không thể chọn giữa chúng: org.jboss.weld.exceptions.AmbiguousResolutionException: WELD-001335: Ambiguous dependencies for type Logger Phải làm gì? Có một số biến thể có sẵn. Cách đơn giản nhất là chú thích @Vetoed cho một hạt CDI để bộ chứa CDI không coi lớp này là một hạt CDI. Nhưng có một cách tiếp cận thú vị hơn nhiều. Một hạt CDI có thể được đánh dấu là "thay thế" bằng cách sử dụng chú thích @Alternativeđược mô tả trong chương " 4.7. Alternatives " của tài liệu Weld CDI. Nó có nghĩa là gì? Điều này có nghĩa là trừ khi chúng tôi nói rõ ràng là sử dụng nó, nếu không nó sẽ không được chọn. Đây là một phiên bản thay thế của đậu. Hãy đánh dấu đậu NetworkLogger là @Alternative và chúng ta có thể thấy mã được thực thi lại và được SystemOutLogger sử dụng. Để kích hoạt giải pháp thay thế, chúng ta phải có tệp Beans.xml . Câu hỏi có thể nảy sinh: " Beans.xml, tôi đặt bạn ở đâu? " Vì vậy, hãy đặt tệp một cách chính xác:
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc
Ngay sau khi chúng tôi có tệp này, tạo phẩm có mã của chúng tôi sẽ được gọi là “ Kho lưu trữ Bean rõ ràng ”. Bây giờ chúng ta có 2 cấu hình riêng biệt: phần mềm và xml. Vấn đề là họ sẽ tải cùng một dữ liệu. Ví dụ: định nghĩa Bean DataSource sẽ được tải 2 lần và chương trình của chúng ta sẽ bị lỗi khi thực thi, bởi vì Bộ chứa CDI sẽ coi chúng là 2 hạt riêng biệt (mặc dù trên thực tế chúng là cùng một lớp, điều mà bộ chứa CDI đã học được hai lần). Để tránh điều này có 2 lựa chọn:
  • xóa dòng này initializer.addPackages(App.class.getPackage())và thêm dấu hiệu thay thế cho tệp xml:
<beans
    xmlns="http://xmlns.jcp.org/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://xmlns.jcp.org/xml/ns/javaee
        http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd">
    <alternatives>
        <class>ru.javarush.NetworkLogger</class>
    </alternatives>
</beans>
  • thêm một thuộc tính bean-discovery-modecó giá trị " none " vào phần tử gốc của đậu và chỉ định một thuộc tính thay thế theo chương trình:
initializer.addPackages(App.class.getPackage());
initializer.selectAlternatives(NetworkLogger.class);
Do đó, bằng cách sử dụng giải pháp thay thế CDI, vùng chứa có thể xác định loại đậu nào sẽ được chọn. Điều thú vị là, nếu bộ chứa CDI biết một số lựa chọn thay thế cho cùng một giao diện thì chúng ta có thể biết nó bằng cách chỉ ra mức độ ưu tiên bằng cách sử dụng chú thích @Priority(Kể từ CDI 1.1).
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Vòng loại

Riêng biệt, đáng để thảo luận về những thứ như vòng loại. Vòng loại được biểu thị bằng chú thích phía trên hạt và tinh chỉnh việc tìm kiếm hạt. Và bây giờ biết thêm chi tiết. Điều thú vị là bất kỳ hạt CDI nào trong mọi trường hợp đều có ít nhất một vòng loại - @Any. Nếu chúng ta không chỉ định BẤT KỲ vòng loại nào phía trên đậu, nhưng sau đó chính bộ chứa CDI sẽ thêm @Anymột vòng loại khác vào vòng loại - @Default. Nếu chúng ta chỉ định bất kỳ điều gì (ví dụ: chỉ định rõ ràng @Any), thì bộ hạn định @Default sẽ không được tự động thêm vào. Nhưng cái hay của vòng loại là bạn có thể tạo vòng loại của riêng mình. Vòng loại hầu như không khác gì các chú thích, bởi vì thực chất đây chỉ là chú thích được viết theo cách đặc biệt. Ví dụ: bạn có thể nhập Enum cho loại giao thức:
public enum ProtocolType {
    HTTP, HTTPS
}
Tiếp theo, chúng ta có thể tạo một bộ hạn định sẽ tính đến loại này:
@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface Protocol {
    ProtocolType value();
    @Nonbinding String comment() default "";
}
Điều đáng lưu ý là các trường được đánh dấu là @Nonbindingkhông ảnh hưởng đến việc xác định vòng loại. Bây giờ bạn cần chỉ định vòng loại. Nó được biểu thị phía trên loại đậu (để CDI biết cách xác định nó) và phía trên Điểm tiêm (với chú thích @Inject, để bạn hiểu loại đậu nào cần tìm để tiêm ở nơi này). Ví dụ: chúng ta có thể thêm một số lớp có vòng loại. Để đơn giản, trong bài viết này, chúng tôi sẽ thực hiện chúng bên trong NetworkLogger:
public interface Sender {
	void send(byte[] data);
}

@Protocol(ProtocolType.HTTP)
public static class HTTPSender implements Sender{
	public void send(byte[] data) {
		System.out.println("sended via HTTP");
	}
}

@Protocol(ProtocolType.HTTPS)
public static class HTTPSSender implements Sender{
	public void send(byte[] data) {
		System.out.println("sended via HTTPS");
	}
}
Và sau đó khi thực hiện Tiêm, chúng tôi sẽ chỉ định một bộ hạn định sẽ ảnh hưởng đến lớp nào sẽ được sử dụng:
@Inject
@Protocol(ProtocolType.HTTPS)
private Sender sender;
Tuyệt vời phải không?) Nó có vẻ đẹp, nhưng không rõ tại sao. Bây giờ hãy tưởng tượng như sau:
Protocol protocol = new Protocol() {
	@Override
	public Class<? extends Annotation> annotationType() {
		return Protocol.class;
	}
	@Override
	public ProtocolType value() {
		String value = "HTTP";
		return ProtocolType.valueOf(value);
	}
};
container.select(NetworkLogger.Sender.class, protocol).get().send(null);
Bằng cách này, chúng ta có thể ghi đè giá trị nhận để có thể tính toán động. Ví dụ: nó có thể được lấy từ một số cài đặt. Sau đó, chúng tôi có thể thay đổi cách triển khai ngay lập tức mà không cần biên dịch lại hoặc khởi động lại chương trình/máy chủ. Nó trở nên thú vị hơn nhiều phải không? )
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Nhà sản xuất

Một tính năng hữu ích khác của CDI là nhà sản xuất. Đây là các phương thức đặc biệt (chúng được đánh dấu bằng chú thích đặc biệt) được gọi khi một số Bean yêu cầu chèn phần phụ thuộc. Thông tin chi tiết hơn được mô tả trong tài liệu, ở phần " 2.2.3. Phương pháp của nhà sản xuất ". Ví dụ đơn giản nhất:
@Produces
public Integer getRandomNumber() {
	return new Random().nextInt(100);
}
Bây giờ, khi Đưa vào các trường kiểu Số nguyên, phương thức này sẽ được gọi và một giá trị sẽ được lấy từ nó. Ở đây chúng ta nên hiểu ngay rằng khi nhìn thấy từ khóa mới, chúng ta phải hiểu ngay rằng đây KHÔNG phải là đậu CDI. Nghĩa là, một thể hiện của lớp Random sẽ không trở thành một CDI Bean chỉ vì nó được bắt nguồn từ thứ gì đó điều khiển bộ chứa CDI (trong trường hợp này là nhà sản xuất).
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Máy đánh chặn

Interceptor là những kẻ chặn đường “can thiệp” vào công việc. Trong CDI điều này được thực hiện khá rõ ràng. Hãy xem cách chúng ta có thể ghi nhật ký bằng trình thông dịch (hoặc trình chặn). Đầu tiên, chúng ta cần mô tả ràng buộc với thiết bị chặn. Giống như nhiều thứ khác, việc này được thực hiện bằng cách sử dụng chú thích:
@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface ConsoleLog {
}
Điều chính ở đây là đây là một ràng buộc cho phần chặn ( @InterceptorBinding), phần này sẽ được kế thừa bởi phần mở rộng ( @InterceptorBinding). Bây giờ hãy viết chính phần chặn:
@Interceptor
@ConsoleLog
public class LogInterceptor {
    @AroundInvoke
    public Object log(InvocationContext ic) throws Exception {
        System.out.println("Invocation method: " + ic.getMethod().getName());
        return ic.proceed();
    }
}
Bạn có thể đọc thêm về cách viết các phần chặn trong ví dụ từ thông số kỹ thuật: " 1.3.6. Ví dụ về phần chặn ". Chà, tất cả những gì chúng ta phải làm là bật thiết bị cảm biến. Để thực hiện việc này, hãy chỉ định chú thích liên kết phía trên phương thức đang được thực thi:
@ConsoleLog
public void print(String message) {
Và bây giờ là một chi tiết rất quan trọng khác. Bộ chặn bị tắt theo mặc định và phải được bật theo cách tương tự như các lựa chọn thay thế. Ví dụ: trong tệp Beans.xml :
<interceptors>
	<class>ru.javarush.LogInterceptor</class>
</interceptors>
Như bạn có thể thấy, nó khá đơn giản.
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Sự kiện & Người quan sát

CDI cũng cung cấp mô hình về các sự kiện và người quan sát. Ở đây mọi thứ không rõ ràng như với thiết bị đánh chặn. Vì vậy, Sự kiện trong trường hợp này hoàn toàn có thể là bất kỳ lớp nào; không cần gì đặc biệt để mô tả. Ví dụ:
public class LogEvent {
    Date date = new Date();
    public String getDate() {
        return date.toString();
    }
}
Bây giờ ai đó nên chờ đợi sự kiện này:
public class LogEventListener {
    public void logEvent(@Observes LogEvent event){
        System.out.println("Message Date: " + event.getDate());
    }
}
Điều chính ở đây là chỉ định chú thích @Observes, cho biết rằng đây không chỉ là một phương thức mà còn là một phương thức nên được gọi do quan sát các sự kiện của loại LogEvent. Chà, bây giờ chúng ta cần một người sẽ xem:
public class LogObserver {
    @Inject
    private Event<LogEvent> event;
    public void observe(LogEvent logEvent) {
        event.fire(logEvent);
    }
}
Chúng tôi có một phương thức duy nhất sẽ thông báo cho vùng chứa rằng một sự kiện Sự kiện đã xảy ra đối với loại sự kiện LogEvent. Bây giờ tất cả những gì còn lại là sử dụng người quan sát. Ví dụ: trong NetworkLogger, chúng ta có thể thêm phần chèn vào trình quan sát của mình:
@Inject
private LogObserver observer;
Và trong phương thức print, chúng ta có thể thông báo cho người quan sát rằng chúng ta có một sự kiện mới:
public void print(String message) {
	observer.observe(new LogEvent());
Điều quan trọng cần biết là các sự kiện có thể được xử lý trong một luồng hoặc nhiều luồng. Để xử lý không đồng bộ, hãy sử dụng một phương thức .fireAsync(thay vì .fire) và chú thích @ObservesAsync(thay vì @Observe). Ví dụ: nếu tất cả các sự kiện được thực thi trong các luồng khác nhau, thì nếu 1 luồng đưa ra Ngoại lệ, thì các luồng khác sẽ có thể thực hiện công việc của chúng cho các sự kiện khác. Bạn có thể đọc thêm về các sự kiện trong CDI, như thường lệ, trong phần đặc tả, ở chương " 10. Sự kiện ".
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

đồ trang trí

Như chúng ta đã thấy ở trên, nhiều mẫu thiết kế khác nhau được thu thập dưới cánh CDI. Và đây là một cái khác - một người trang trí. Đây là một điều rất thú vị. Chúng ta hãy nhìn vào lớp học này:
@Decorator
public abstract class LoggerDecorator implements Logger {
    public final static String ANSI_GREEN = "\u001B[32m";
    public static final String ANSI_RESET = "\u001B[0m";

    @Inject
    @Delegate
    private Logger delegate;

    @Override
    public void print(String message) {
        delegate.print(ANSI_GREEN + message + ANSI_RESET);
    }
}
Bằng cách khai báo nó là một trình trang trí, chúng tôi nói rằng khi sử dụng bất kỳ triển khai Logger nào, “tiện ích bổ sung” này sẽ được sử dụng, tiện ích bổ sung này biết cách triển khai thực sự, được lưu trữ trong trường đại biểu (vì nó được đánh dấu bằng chú thích @Delegate). Trình trang trí chỉ có thể được liên kết với một hạt CDI, bản thân nó không phải là phần chặn hay phần trang trí. Một ví dụ cũng có thể được nhìn thấy trong đặc tả: " 1.3.7. Decorator example ". Công cụ trang trí, giống như thiết bị chặn, phải được bật. Ví dụ: trong Beans.xml :
<decorators>
	<class>ru.javarush.LoggerDecorator</class>
</decorators>
Để biết thêm chi tiết, xem tài liệu tham khảo về mối hàn: " Chương 10. Trang trí ".

Vòng đời

Đậu có vòng đời riêng của chúng. Nó trông giống như thế này:
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc
Như bạn có thể thấy trong hình, chúng tôi có cái gọi là lệnh gọi lại vòng đời. Đây là những chú thích sẽ yêu cầu bộ chứa CDI gọi một số phương thức nhất định ở một giai đoạn nhất định trong vòng đời của Bean. Ví dụ:
@PostConstruct
public void init() {
	System.out.println("Inited");
}
Phương thức này sẽ được gọi khi một CDI Bean được khởi tạo bởi một container. Điều tương tự sẽ xảy ra với @PreDestroy khi đậu bị hủy khi không còn cần thiết nữa. Không phải tự nhiên mà từ viết tắt CDI có chứa chữ C - Context. Đậu trong CDI có tính chất theo ngữ cảnh, nghĩa là vòng đời của chúng phụ thuộc vào ngữ cảnh mà chúng tồn tại trong vùng chứa CDI. Để hiểu rõ hơn về điều này, bạn nên đọc phần đặc tả “ 7. Vòng đời của các phiên bản theo ngữ cảnh ”. Cũng cần biết rằng bản thân vùng chứa có vòng đời mà bạn có thể đọc trong phần “ Sự kiện vòng đời của vùng chứa ”.
Một chuyến tham quan ngắn gọn vào phần tiêm phụ thuộc hoặc

Tổng cộng

Ở trên chúng ta đã xem xét phần nổi của tảng băng chìm có tên CDI. CDI là một phần của đặc tả JEE và được sử dụng trong môi trường JavaEE. Những người sử dụng Spring không sử dụng CDI mà sử dụng DI, tức là đây là những thông số kỹ thuật hơi khác nhau. Nhưng biết và hiểu rõ những điều trên, bạn có thể dễ dàng thay đổi suy nghĩ của mình. Xem xét rằng Spring hỗ trợ các chú thích từ thế giới CDI (cùng một Tiêm). Tài liệu bổ sung: #Viacheslav
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION