Bạn có thể sử dụng @Autowired với các trường tĩnh không?


Câu trả lời:


122

Tóm lại, không. Bạn không thể tự động hoặc dây thủ công các trường tĩnh trong Spring. Bạn sẽ phải viết logic của riêng bạn để làm điều này.


2
Khi bạn tìm thấy mã cũ làm điều này, đó là một mô hình chống. Nheo mắt, nghiêng đầu và tìm cách tốt hơn để giải quyết vấn đề. Bạn sẽ vui vì bạn đã làm.
Joseph Lust

2
này câu trả lời cũng là hữu ích về mùa xuân@AutoWired
Kevin Meredith

116
@Component("NewClass")
public class NewClass{
    private static SomeThing someThing;

    @Autowired
    public void setSomeThing(SomeThing someThing){
        NewClass.someThing = someThing;
    }
}

1
bất kỳ ý tưởng làm thế nào tôi có thể sử dụng phương pháp này khi khởi tạo một kho lưu trữ?
kiedysktos

3
Nhược điểm: Không có gì đảm bảo someThingđã được khởi tạo nếu được truy cập tĩnh: NewClass.staticMethodWhichUsesSomething();có thể ném NPE nếu được sử dụng trước khi khởi tạo ứng dụng
Neeraj

Bạn có thể tránh cảnh báo Instance methods should not write to "static" fields (squid:S2696)?
user7294900

@ user7294900: chỉ tắt cảnh báo cho trường hợp này, trường hợp rất cụ thể.
izogfif

@izogfif vẫn là một vấn đề nếu tôi chọn giải pháp này trong các trường hợp và lớp học rộng
user7294900

67

@Autowired có thể được sử dụng với setters để bạn có thể có một setter sửa đổi trường tĩnh.

Chỉ cần một đề nghị cuối cùng ... ĐỪNG


54
Tại sao bạn đề nghị không làm điều này?
Jon Lorusso

3
Hmmm .. cảm giác của tôi về lý do tại sao nó không được khuyến khích, bởi vì sau đó, thể hiện tĩnh trong lớp nằm ngoài tầm kiểm soát của mùa xuân. Khi tiêm tĩnh lĩnh vực là các tài liệu tham khảo cho tất cả các trường hợp của các đối tượng của (xung quanh) lớp tương ứng. Nhưng, hành vi này có thể chính xác là những gì được dự kiến ​​sẽ xảy ra, do đó có thể được coi là một lỗi hoặc một tính năng ...
matthaeus

1
Có @matthaeus, đó chính xác là tính năng tôi mong đợi khi cần truy cập org.springframework.core.env.En @Component public class SpringAppEnv{ public static Environment _env; @Autowired public void setEnv(Environment env) {_env = env;} }
Môi trường

@JonLorusso và tất cả Bởi vì khi trình nạp lớp tải các giá trị tĩnh, bối cảnh Spring vẫn chưa được tải. Vì vậy, trình nạp lớp sẽ không tiêm đúng lớp tĩnh vào bean và sẽ thất bại. Câu trả lời được cung cấp bởi Andrea T
Jeril Kuruvila

14

Khởi tạo thành phần tự động của bạn trong phương thức @PostConstruct

@Component
public class TestClass {
   private static AutowiredTypeComponent component;

   @Autowired
   private AutowiredTypeComponent autowiredComponent;

   @PostConstruct
   private void init() {
      component = this.autowiredComponent;
   }

   public static void testMethod() {
      component.callTestMethod();
   }
}

Bạn có thể tránh cảnh báo Instance methods should not write to "static" fields (squid:S2696)?
user7294900

Bạn cũng có thể làm điều này trực tiếp thông qua các nhà xây dựng.
gagarwa

5

Tạo một bean mà bạn có thể autowire sẽ khởi tạo biến tĩnh làm hiệu ứng phụ.


4

Bạn có thể đạt được điều này bằng cách sử dụng ký hiệu XMLMethodInvokingFactoryBean. Ví dụ nhìn vào đây .

private static StaticBean staticBean;

public void setStaticBean(StaticBean staticBean) {
   StaticBean.staticBean = staticBean;
}

Bạn nên đặt mục tiêu sử dụng thuốc tiêm mùa xuân khi có thể vì đây là cách tiếp cận được khuyến nghị nhưng điều này không phải lúc nào cũng có thể vì tôi chắc chắn bạn có thể tưởng tượng vì không phải mọi thứ đều có thể được kéo từ thùng chứa lò xo hoặc bạn có thể xử lý các hệ thống cũ.

Kiểm tra lưu ý cũng có thể khó khăn hơn với phương pháp này.


1

Bạn có thể sử dụng ApplicationContextAware

@Component
public class AppContext implements ApplicationContextAware{
    public static ApplicationContext applicationContext;

    public AppBeans(){
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

sau đó

static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);

1

Muốn thêm vào câu trả lời rằng trường tĩnh tự động (hoặc hằng số) sẽ bị bỏ qua, nhưng cũng sẽ không tạo ra bất kỳ lỗi nào:

@Autowired
private static String staticField = "staticValue";

0

Tuyên bố miễn trừ trách nhiệm Đây không phải là tiêu chuẩn và rất có thể là một cách tốt hơn để làm điều này. Không có câu trả lời nào ở trên giải quyết các vấn đề nối dây trường tĩnh công cộng.

Tôi muốn hoàn thành ba điều.

  1. Sử dụng lò xo để "Autowire" (Tôi đang sử dụng @Value)
  2. Đưa ra một giá trị tĩnh công khai
  3. Ngăn chặn sửa đổi

Đối tượng của tôi trông như thế này

private static String BRANCH = "testBranch";

@Value("${content.client.branch}")
public void finalSetBranch(String branch) {
    BRANCH = branch;
}

public static String BRANCH() {
    return BRANCH;
}

Chúng tôi đã kiểm tra 1 & 2 ngay bây giờ để làm thế nào để chúng tôi ngăn chặn các cuộc gọi đến setter, vì chúng tôi không thể ẩn nó.

@Component
@Aspect
public class FinalAutowiredHelper {

@Before("finalMethods()")
public void beforeFinal(JoinPoint joinPoint) {
    throw new FinalAutowiredHelper().new ModifySudoFinalError("");
}

@Pointcut("execution(* com.free.content.client..*.finalSetBranch(..))")
public void finalMethods() {}


public class ModifySudoFinalError extends Error {
    private String msg;

    public ModifySudoFinalError(String msg) {
        this.msg = msg;
    }

    @Override
    public String getMessage() {
        return "Attempted modification of a final property: " + msg;
    }
}

Khía cạnh này sẽ bao bọc tất cả các phương thức bắt đầu bằng cuối cùng và đưa ra lỗi nếu chúng được gọi.

Tôi không nghĩ rằng điều này đặc biệt hữu ích, nhưng nếu bạn là ocd và muốn giữ cho bạn tách đậu và cà rốt thì đây là một cách để làm điều đó một cách an toàn.

Mùa xuân quan trọng không gọi các khía cạnh của bạn khi nó gọi một chức năng. Làm cho điều này dễ dàng hơn, xấu đến mức tôi đã tìm ra logic trước khi tìm ra điều đó.


-1
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);

2
Mặc dù mã này có thể giải quyết câu hỏi, bao gồm giải thích về cách thức và lý do giải quyết vấn đề này thực sự sẽ giúp cải thiện chất lượng bài đăng của bạn và có thể dẫn đến nhiều lượt bình chọn hơn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ người hỏi bây giờ. Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra dấu hiệu về những hạn chế và giả định được áp dụng.
tiếng bíp đôi

Tôi nghĩ rằng câu trả lời này có thể không cần bất kỳ lời giải thích nào cả.
Chaklader Asfak Arefe
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.