@Autowired
Statik alanlarla kullanmanın bir yolu var mı ? Değilse, bunu yapmanın başka yolları var mı?
Yanıtlar:
Kısacası hayır. Spring'de statik alanları otomatik kablolama veya manuel olarak bağlayamazsınız. Bunu yapmak için kendi mantığınızı yazmanız gerekecek.
@AutoWired
@Component("NewClass")
public class NewClass{
private static SomeThing someThing;
@Autowired
public void setSomeThing(SomeThing someThing){
NewClass.someThing = someThing;
}
}
someThing
Statik olarak erişilirse başlatılan bir garanti yok : NewClass.staticMethodWhichUsesSomething();
uygulama başlatılmadan önce kullanılırsa bir NPE atabilir
Instance methods should not write to "static" fields (squid:S2696)
?
@Autowired
ayarlayıcılarla birlikte kullanılabilir, böylece statik bir alanı değiştiren bir ayarlayıcıya sahip olabilirsiniz.
Sadece son bir öneri ... YAPMAYIN
@Component public class SpringAppEnv{ public static Environment _env; @Autowired public void setEnv(Environment env) {_env = env;} }
@ PostConstruct yönteminde otomatik kablolu bileşeninizi başlatın
@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)
?
Bunu XML gösterimi ve MethodInvokingFactoryBean
. Örnek için buraya bakın .
private static StaticBean staticBean;
public void setStaticBean(StaticBean staticBean) {
StaticBean.staticBean = staticBean;
}
Önerilen yaklaşım bu olduğundan, mümkünse yaylı enjeksiyon kullanmayı hedeflemelisiniz. ancak bu her zaman mümkün değildir, çünkü her şeyin yaylı hazneden çekilemeyeceğini veya eski sistemlerle uğraşabileceğinizi hayal edebileceğinizden eminim.
Not testi, bu yaklaşımla daha zor olabilir.
Otomatik kablolama statik alanının (veya sabitinin) yok sayılacağı, ancak aynı zamanda herhangi bir hata oluşturmayacağı yanıtlarına eklemek istendi:
@Autowired
private static String staticField = "staticValue";
ApplicationContextAware'i kullanabilirsiniz
@Component
public class AppContext implements ApplicationContextAware{
public static ApplicationContext applicationContext;
public AppBeans(){
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
sonra
static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);
Feragatname Bu hiçbir şekilde standart değildir ve bunu yapmanın daha iyi bir yolu olabilir. Yukarıdaki cevapların hiçbiri bir kamusal statik alanın kablolanmasıyla ilgili sorunları ele almamaktadır.
Üç şeyi başarmak istedim.
Benim nesnem buna benziyor
private static String BRANCH = "testBranch";
@Value("${content.client.branch}")
public void finalSetBranch(String branch) {
BRANCH = branch;
}
public static String BRANCH() {
return BRANCH;
}
1 & 2'yi zaten işaretledik, gizleyemeyeceğimiz için ayarlayıcıya gelen çağrıları nasıl engelleyeceğiz.
@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;
}
}
Bu özellik, finalden başlayarak tüm yöntemleri sarmalar ve çağrılırsa bir hata verir.
Bunun özellikle yararlı olduğunu sanmıyorum, ancak eğer okkalıysanız ve sizi bezelye ve havuç ayrı tutmaktan hoşlanıyorsanız, bu güvenli bir şekilde yapmanın bir yoludur.
Önemli Bahar, bir işlevi çağırdığında veçhelerinizi çağırmaz. Bunu daha kolay hale getirdi, kötüye doğru anlamadan önce mantığı çözdüm.
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);