a

Câu hỏi Quét các chú thích Java khi chạy


Cách tốt nhất để tìm kiếm toàn bộ classpath cho một lớp chú thích là gì?

Tôi đang làm một thư viện và tôi muốn cho phép người dùng chú thích các lớp của họ, vì vậy khi ứng dụng Web bắt đầu, tôi cần phải quét toàn bộ classpath cho một số chú thích nhất định.

Bạn có biết một thư viện hoặc một cơ sở Java để làm điều này?

Chỉnh sửa: Tôi đang suy nghĩ về một cái gì đó giống như chức năng mới cho Java EE 5 Web Services hoặc EJB's. Bạn chú thích lớp học của mình @WebService hoặc là @EJB và hệ thống tìm thấy các lớp này trong khi tải để chúng có thể truy cập từ xa.


206
2017-11-03 16:17


gốc




Các câu trả lời:


Sử dụng org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider 

API

Nhà cung cấp thành phần quét đường dẫn lớp từ gói cơ sở. Sau đó nó áp dụng loại trừ và bao gồm các bộ lọc cho các lớp kết quả để tìm các ứng cử viên.

ClassPathScanningCandidateComponentProvider scanner =
new ClassPathScanningCandidateComponentProvider(<DO_YOU_WANT_TO_USE_DEFALT_FILTER>);

scanner.addIncludeFilter(new AnnotationTypeFilter(<TYPE_YOUR_ANNOTATION_HERE>.class));

for (BeanDefinition bd : scanner.findCandidateComponents(<TYPE_YOUR_BASE_PACKAGE_HERE>))
    System.out.println(bd.getBeanClassName());

171
2017-09-12 15:11



Cảm ơn đã cung cấp thông tin. Bạn cũng biết cách quét đường dẫn lớp cho các lớp có các trường có chú thích tùy chỉnh không? - Javatar
@Javatar Sử dụng API phản chiếu của Java. <YOUR_CLASS> .class.getFields () Đối với mỗi trường, gọi getAnnotation (<YOUR_ANNOTATION>) - Arthur Ronald
@ArthurRonaldFDGarcia, làm thế nào tôi có thể quét sub package như thế? - CycDemo
LƯU Ý: Nếu bạn đang làm điều này bên trong một ứng dụng Spring, Spring sẽ vẫn đánh giá và hành động dựa trên @Conditional chú thích. Vì vậy, nếu một lớp học có @Conditional giá trị trả về false, nó sẽ không được trả về bởi findCandidateComponents, ngay cả khi nó khớp với bộ lọc của máy quét. Điều này đã ném tôi ngày hôm nay - tôi đã kết thúc bằng cách sử dụng giải pháp của Jonathan dưới đây để thay thế. - Kidburla
@ArthurRonald Xin lỗi, Arthur. Ý tôi là BeanDefinition đối tượng không cung cấp một cách để đưa lớp học trực tiếp. Điều gần nhất dường như là getBeanClassName trả về tên lớp đầy đủ, nhưng hành vi chính xác của phương thức này không rõ ràng. Ngoài ra, không rõ lớp trình nạp lớp nào được tìm thấy trong đó. - Max


Và một giải pháp khác là Google phản xạ.

Đánh giá nhanh:

  • Giải pháp mùa xuân là cách để đi nếu bạn đang sử dụng Spring. Nếu không thì đó là một sự phụ thuộc lớn.
  • Sử dụng ASM trực tiếp là một chút cồng kềnh.
  • Sử dụng Java Assist trực tiếp cũng rất phức tạp.
  • Annovention là siêu nhẹ và thuận tiện. Chưa có tích hợp maven.
  • Google phản ánh kéo vào bộ sưu tập của Google. Lập chỉ mục mọi thứ và sau đó là siêu nhanh.

135
2017-08-02 21:08



new Reflections("my.package").getTypesAnnotatedWith(MyAnnotation.class). c'est tout. - zapp
hoàn hảo cho quét mục đích chung, ty! - gibffe
Tôi có cần phải chỉ định tên gói không? ký tự đại diện? những gì cho tất cả các lớp trong classpath? - Sunnyday


(Edit: FastClasspathScanner bây giờ đã được đổi tên thành ClassGraph)

Thử ClassGraph. (Disclaimer, tôi là tác giả). ClassGraph hỗ trợ quét chú thích, hoặc ở thời gian chạy hoặc tại thời gian xây dựng, nhưng cũng nhiều hơn nữa. ClassGraph có thể xây dựng một biểu diễn trừu tượng của toàn bộ đồ thị lớp (tất cả các lớp, chú thích, phương thức, tham số phương thức và trường) trong bộ nhớ, cho tất cả các lớp trên classpath, hoặc cho các lớp trong các gói thuộc danh sách trắng, và bạn có thể truy vấn đồ thị lớp đó bạn muốn. Hỗ trợ ClassGraph thêm các cơ chế đặc điểm lớp và các trình nạp lớp so với bất kỳ máy quét nào khác, và cũng hoạt động liên tục với hệ thống mô-đun JPMS mới, vì vậy nếu bạn căn cứ mã của mình trên ClassGraph, mã của bạn sẽ được tối đa di động. Xem API tại đây.


30
2017-08-17 22:53



Điều này cần Java 8 để chạy? - David George
Cập nhật để sử dụng Java7, không có vấn đề gì. Chỉ cần loại bỏ các annoations và chuyển đổi các chức năng để sử dụng các lớp bên trong vô danh. Tôi thích kiểu 1 tệp. Các mã là tốt đẹp một sạch, vì vậy mặc dù nó không hỗ trợ một vài điều tôi muốn (class + chú thích cùng một lúc) Tôi nghĩ rằng sẽ được khá damn dễ dàng để thêm. Làm tốt lắm! Nếu ai đó không thể quản lý công việc để sửa đổi cho v7, họ có lẽ nên đi với Reflections. Ngoài ra, nếu bạn đang sử dụng ổi / etc và muốn thay đổi các bộ sưu tập, dễ dàng như chiếc bánh. Những bình luận tuyệt vời bên trong. - Andrew Backer
Tài liệu này rất ấn tượng. - dnault
@lamostreta Tôi đang làm việc về điều này ngay bây giờ, nên được phát hành khá sớm. - Luke Hutchison
@ Alexandros cảm ơn, bạn nên kiểm tra ClassGraph, nó được cải thiện đáng kể so với FastClasspathScanner. - Luke Hutchison


Nếu bạn muốn thực sự trọng lượng nhẹ (không phụ thuộc, API đơn giản, tệp jar 15 kb) và rất nhanh giải pháp, hãy xem annotation-detector tìm thấy tại https://github.com/rmuller/infomas-asl 

Disclaimer: Tôi là tác giả.


17
2017-11-21 09:05





Bạn có thể sử dụng Java Processing Pluggable Annotation Processing API để viết bộ xử lý chú thích sẽ được thực thi trong suốt quá trình biên dịch và sẽ thu thập tất cả các lớp chú thích và xây dựng tệp chỉ mục để sử dụng thời gian chạy.

Đây là cách nhanh nhất có thể để thực hiện khám phá lớp được chú thích bởi vì bạn không cần phải quét đường dẫn lớp của bạn khi chạy, thường hoạt động rất chậm. Cách tiếp cận này cũng làm việc với bất kỳ trình nạp lớp nào và không chỉ với các Trình tải URLClassLoaders thường được các trình quét thời gian chạy hỗ trợ.

Cơ chế trên đã được triển khai trong ClassIndex thư viện.

Để sử dụng chú thích, chú thích tùy chỉnh của bạn với @IndexAnnotated meta-chú thích. Điều này sẽ tạo ra tại thời gian biên dịch một tệp chỉ mục: META-INF / chú thích / com / test / YourCustomAnnotation liệt kê tất cả các lớp được chú thích. Bạn có thể thừa nhận chỉ mục trong thời gian chạy bằng cách thực thi:

ClassIndex.getAnnotated(com.test.YourCustomAnnotation.class)

13
2017-12-27 08:31





Sử dụng ServiceLoader, hoặc là thực hiện của riêng bạn nếu bạn không có trong Java 6.

Có lẽ một bộ xử lý chú thích có thể tạo ra các tệp cần thiết theo META-INF / dịch vụ tại thời điểm biên dịch.


10
2017-11-03 17:41





Thử Scannotation.

Nó có thể được sử dụng để tìm kiếm classpath hoặc thư mục lib ứng dụng web của bạn cho các chú thích cụ thể.


6
2017-11-03 23:59



-1 có vẻ như thư viện này đã lỗi thời, nó sử dụng phiên bản javassist rất cũ mà không thể đọc các tệp lớp java 8. Sử dụng "phản xạ" thay vào đó (xem câu trả lời của Jonathan) - Bastian Voigt