มีวิธีใช้@Autowired
กับฟิลด์สแตติกหรือไม่ ถ้าไม่มีวิธีอื่นที่จะทำเช่นนี้?
มีวิธีใช้@Autowired
กับฟิลด์สแตติกหรือไม่ ถ้าไม่มีวิธีอื่นที่จะทำเช่นนี้?
คำตอบ:
ในระยะสั้นไม่มี คุณไม่สามารถอัตโนมัติหรือผูกสายฟิลด์คงที่ด้วยตนเองในฤดูใบไม้ผลิ คุณจะต้องเขียนตรรกะของคุณเองเพื่อทำสิ่งนี้
@AutoWired
@Component("NewClass")
public class NewClass{
private static SomeThing someThing;
@Autowired
public void setSomeThing(SomeThing someThing){
NewClass.someThing = someThing;
}
}
someThing
ได้รับการเริ่มต้นถ้าเข้าถึงแบบคงที่: NewClass.staticMethodWhichUsesSomething();
อาจโยน NPE ถ้าใช้ก่อนการเริ่มต้นแอป
Instance methods should not write to "static" fields (squid:S2696)
หรือไม่?
@Autowired
สามารถใช้กับตัวตั้งค่าเพื่อให้คุณสามารถตั้งค่าตัวปรับเปลี่ยนฟิลด์แบบคงที่
ข้อเสนอแนะสุดท้ายเพียงข้อเดียว ... ไม่
@Component public class SpringAppEnv{ public static Environment _env; @Autowired public void setEnv(Environment env) {_env = env;} }
เริ่มส่วนประกอบที่เป็นอัตโนมัติในเมธอด @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();
}
}
Instance methods should not write to "static" fields (squid:S2696)
หรือไม่?
สร้าง bean ที่คุณสามารถ autowire ซึ่งจะเริ่มต้นตัวแปรคงที่เป็นผลข้างเคียง
คุณสามารถบรรลุนี้โดยใช้สัญกรณ์ XMLMethodInvokingFactoryBean
และ สำหรับตัวอย่างดูที่นี่
private static StaticBean staticBean;
public void setStaticBean(StaticBean staticBean) {
StaticBean.staticBean = staticBean;
}
คุณควรตั้งเป้าหมายที่จะใช้สปริงสปริงเนื่องจากเป็นวิธีที่แนะนำแต่มันไม่ได้เป็นไปได้เสมอเพราะฉันแน่ใจว่าคุณสามารถจินตนาการได้ว่าไม่ใช่ทุกสิ่งที่สามารถดึงออกมาจากสปริงคอนเทนเนอร์หรือคุณอาจจัดการกับระบบเดิม
การทดสอบหมายเหตุอาจทำได้ยากขึ้นด้วยวิธีนี้
ต้องการเพิ่มคำตอบว่าจะไม่สนใจฟิลด์การวางสายอัตโนมัติ (หรือค่าคงที่) แต่จะไม่สร้างข้อผิดพลาดใด ๆ :
@Autowired
private static String staticField = "staticValue";
คุณสามารถใช้ ApplicationContextAware
@Component
public class AppContext implements ApplicationContextAware{
public static ApplicationContext applicationContext;
public AppBeans(){
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
แล้วก็
static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);
ข้อจำกัดความรับผิดชอบนี่ไม่ใช่มาตรฐานและอาจเป็นวิธีที่ดีกว่าในการทำสิ่งนี้ ไม่มีคำตอบใดที่กล่าวถึงปัญหาของการเดินสายในเขตข้อมูลสาธารณะ
ฉันต้องการทำสามสิ่งให้สำเร็จ
วัตถุของฉันมีลักษณะเช่นนี้
private static String BRANCH = "testBranch";
@Value("${content.client.branch}")
public void finalSetBranch(String branch) {
BRANCH = branch;
}
public static String BRANCH() {
return BRANCH;
}
เราได้ตรวจสอบ 1 และ 2 แล้วตอนนี้เราจะป้องกันการโทรไปยัง setter ได้อย่างไรเนื่องจากเราไม่สามารถซ่อนมันได้
@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;
}
}
กว้างยาวนี้จะห่อวิธีทั้งหมดที่เริ่มต้นด้วยขั้นสุดท้ายและโยนข้อผิดพลาดถ้าพวกเขาถูกเรียกว่า
ฉันไม่คิดว่ามันจะมีประโยชน์เป็นพิเศษ แต่ถ้าคุณเป็น ocd และอยากให้คุณแยกถั่วกับแครอทนี่เป็นวิธีหนึ่งที่จะทำได้อย่างปลอดภัย
สิ่งสำคัญ Spring ไม่เรียกลักษณะของคุณเมื่อเรียกใช้ฟังก์ชัน ทำให้เรื่องนี้ง่ายขึ้นแย่ไปกว่านั้นฉันก็หาตรรกะก่อนที่จะหามัน
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);