2016-03-06 23 views
8

Giả sử tôi là xây dựng một chiếc xe và tôi có một vài hạt cà phê với hiện thực khác nhauDagger2 tùy chỉnh @Qualifier sử dụng

class Car { 
    @Inject 
    Car(@BrakeType(value="abs")Brake frontBrake, @BrakeType(value="nonabs")Brake rearBrake) { } 
} 

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
public @interface BrakeType { 
    String value(); 
} 

interface Brake {} 

@BrakeType(value="abs") 
class AbsBrakeImpl implements Brake { 
    @Inject AbsBrakeImpl() {} 
} 

@BrakeType(value="nonabs") 
class BrakeImpl implements Brake { 
    @Inject BrakeImpl() {} 
} 

tại sao CarModule tôi phải xác định @Provides cho các loại phanh cụ thể phanh? Loại chú thích tùy chỉnh @BrakeType có đủ để xác định impl nào được chèn vào không? Hay điều đó đòi hỏi phải sử dụng sự phản chiếu, mà dagger2 không sử dụng?

@Module 
public class CarModule { 
    @Provides @BrakeType("abs") 
    public Brake absBrake() { 
     return new AbsBrakeImpl(); 
    } 
    @Provides @BrakeType("nonabs") 
    public Brake nonabsBrake() { 
     return new BrakeImpl(); 
    } 
} 

Trả lời

0

Phản ánh có lẽ không phải là vấn đề lớn ở đây vì nó sẽ xảy ra vào thời gian biên dịch.

Tôi không xem qua source code, nhưng dao găm là bộ xử lý chú thích — nó đăng ký để được gọi bất cứ khi nào một tập hợp các chú thích nhất định được sử dụng. Trong khi vòng loại một mình có lẽ sẽ là đủ để tìm ra những gì bạn dự định, tôi có thể nghĩ ra những lý do sau đây tại sao điều này không thể là giải pháp tốt nhất.

javax.inject.Qualifier là một phần của API lớn hơn và cũng có thể được sử dụng bởi các thư viện khác trong ngữ cảnh khác nhau. Vì vậy, bạn có thể không muốn dao găm tạo mã cho một phương thức, chỉ vì nó được chú thích với một vòng loại.

Lý do khác có thể là do có khả năng tạo vòng loại tùy chỉnh, dao găm sẽ phải kiểm tra mọi chú thích trên mọi phương thức trong mỗi mô-đun và sau đó xác định xem chú thích đó có được chú thích bằng @Qualifier không là một số quan tâm đến nó. Đây là một chi phí không cần thiết.

Có thể có nhiều lý do hơn, nhưng 2 lý do được liệt kê ở đây dường như đủ để khiến người dùng dao găm sử dụng một số loại hợp đồng: @Provides.

Chú thích không ảnh hưởng đến hiệu suất của mã và chú thích bổ sung sẽ không gây hại gì, vì vậy có nhiều thứ để đạt được hơn thua bằng cách xử lý theo cách họ thực hiện.

3

Dagger không xem chú thích định danh trên lớp học, chỉ trên các phương thức @Provides hoặc @Binds. Vì vậy, các chú thích @BrakeType(value="abs") trên lớp học của bạn không có bất kỳ ảnh hưởng nào.

Một cách kinh điển hơn của việc viết mã của bạn là:

class AbsBrakeImpl implements Brake { 
    @Inject AbsBrakeImpl() {} 
} 

class BrakeImpl implements Brake { 
    @Inject BrakeImpl() {} 
} 

@Module 
abstract class CarModule { 
    @Binds @BrakeType("abs") 
    abstract Brake absBrake(AbsBrakeImpl impl); 

    @Binds @BrakeType("nonabs") 
    abstract Brake nonabsBrake(BrakeImpl impl); 
} 

Lưu ý rằng kể từ khi bạn có @Inject trên các nhà thầu triển khai của bạn, bạn chỉ có thể sử dụng Dagger của @Bind để ràng buộc việc triển khai trực tiếp đến giao diện một cách thích hợp có trình độ .

1

Để lưu bản ghi, bạn có thể sử dụng chú thích định danh của riêng bạn (dưới dạng Kiểu phanh) hoặc chỉ sử dụng @Named từ Dagger. dùng cuối cùng này, mã của bạn sẽ giống như thế:

@Inject @Named("abs") Brake frontBrake; 
@Inject @Named("nonabs") Brake rearBrake; 

Và trên mô-đun của bạn:

@Provides @Named("abs") static Brake provideAbsBrake() { 
    return new AbsBrakeImpl(); 
} 
@Provides @Named("nonabs") static Brake provideNonAbsBrake() { 
    return new BrakeImpl(); 
} 

Hãy nhớ sử dụng Dagger ước tên (như cung cấp tiền tố) để có được nhiều nhất của nó. Và trên các mô-đun của bạn, hãy thử sử dụng tất cả các phương thức @Provides tĩnh, làm như vậy việc triển khai kết quả không cần phải khởi tạo nó.

Trong ngắn hạn, Cung cấp và Vòng loại hoạt động cùng nhau nên bạn cần cả hai.


Nguồn: Dagger users guide.

0

@Inject constructor phương tiện cung cấp một loại mà lớp đó, trong trường hợp của bạn, có nghĩa là bạn cung cấp các loại AbsBrakeImplBrakeImpl loại, vì vậy khi bạn cố gắng để tiêm với Brake, dao găm không thể tìm thấy các nhà cung cấp.

Vòng loại trong @Inject constructor không hoạt động, vì loại lớp là duy nhất, chúng tôi không cần phải thêm vòng loại vào.

Vì vậy, trong trường hợp của bạn, hoặc bạn phải sử dụng CarModule nói với Dagger một cách rõ ràng, hoặc thay đổi nhà xây dựng của bạn với

class Car { 
    @Inject 
    Car(AbsBrakeImpl frontBrake, BrakeImpl rearBrake) { } 
} 
Các vấn đề liên quan