Is there some way to use #Autowired with static fields. If not, are there some other ways to do this?
In short, no. You cannot autowire or manually wire static fields in Spring. You'll have to write your own logic to do this.
#Component("NewClass")
public class NewClass{
private static SomeThing someThing;
#Autowired
public void setSomeThing(SomeThing someThing){
NewClass.someThing = someThing;
}
}
#Autowired can be used with setters so you could have a setter modifying an static field.
Just one final suggestion... DON'T
Init your autowired component in #PostConstruct method
#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();
}
}
Create a bean which you can autowire which will initialize the static variable as a side effect.
Wanted to add to answers that auto wiring static field (or constant) will be ignored, but also won't create any error:
#Autowired
private static String staticField = "staticValue";
You can achieve this using XML notation and the MethodInvokingFactoryBean. For an example look here.
private static StaticBean staticBean;
public void setStaticBean(StaticBean staticBean) {
StaticBean.staticBean = staticBean;
}
You should aim to use spring injection where possible as this is the recommended approach but this is not always possible as I'm sure you can imagine as not everything can be pulled from the spring container or you maybe dealing with legacy systems.
Note testing can also be more difficult with this approach.
You can use ApplicationContextAware
#Component
public class AppContext implements ApplicationContextAware{
public static ApplicationContext applicationContext;
public AppBeans(){
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
then
static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);
Disclaimer This is by no means standard and there could very well be a better spring way of doing this. None of the above answers address the issues of wiring a public static field.
I wanted to accomplish three things.
Use spring to "Autowire" (Im using #Value)
Expose a public static value
Prevent modification
My object looks like this
private static String BRANCH = "testBranch";
#Value("${content.client.branch}")
public void finalSetBranch(String branch) {
BRANCH = branch;
}
public static String BRANCH() {
return BRANCH;
}
We have checked off 1 & 2 already now how do we prevent calls to the setter, since we cannot hide it.
#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;
}
}
This aspect will wrap all methods beginning with final and throw an error if they are called.
I dont think this is particularly useful, but if you are ocd and like to keep you peas and carrots separated this is one way to do it safely.
Important Spring does not call your aspects when it calls a function. Made this easier, to bad I worked out the logic before figuring that out.
Generally, setting static field by object instance is a bad practice.
to avoid optional issues you can add synchronized definition, and set it only if private static Logger logger;
#Autowired
public synchronized void setLogger(Logger logger)
{
if (MyClass.logger == null)
{
MyClass.logger = logger;
}
}
:
Solution 1 : Using Constructor #Autowired For Static Field
#Component
public class MyClass {
private static MyService service;
#Autowired
public MyClass(MyService service) {
TestClass.service= service;
}
}
Solution 2 : Using #PostConstruct to set the value to Static Field
#Component
public class MyClass {
private static MyService service;
#Autowired
private MyService srv;
#PostConstruct
public void init() {
this.service= srv;
}
}
Refer here for more detail
I use private static inner Component: FieldSetter, to inject static field: MyBean, at last SelfDestroyBean will help me remove redundant FiledSetter bean
public final class MyClass {
private static MyBean myBean;
#Component
private static class FieldSetter extends SelfDestroyBean {
public FieldSetter(MyBean myBean) {
MyClass.myBean = myBean;
}
}
}
#SuppressWarnings("SpringJavaAutowiredMembersInspection")
public abstract class SelfDestroyBean {
#Autowired
private ApplicationContext context;
#PostConstruct
public void destroy() {
final String[] beanNames = context.getBeanNamesForType(this.getClass());
final BeanDefinitionRegistry registry =
((BeanDefinitionRegistry) context.getAutowireCapableBeanFactory());
for (String beanName : beanNames) {
registry.removeBeanDefinition(beanName);
}
}
}
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);
Related
Is there some way to use #Autowired with static fields. If not, are there some other ways to do this?
In short, no. You cannot autowire or manually wire static fields in Spring. You'll have to write your own logic to do this.
#Component("NewClass")
public class NewClass{
private static SomeThing someThing;
#Autowired
public void setSomeThing(SomeThing someThing){
NewClass.someThing = someThing;
}
}
#Autowired can be used with setters so you could have a setter modifying an static field.
Just one final suggestion... DON'T
Init your autowired component in #PostConstruct method
#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();
}
}
Create a bean which you can autowire which will initialize the static variable as a side effect.
Wanted to add to answers that auto wiring static field (or constant) will be ignored, but also won't create any error:
#Autowired
private static String staticField = "staticValue";
You can achieve this using XML notation and the MethodInvokingFactoryBean. For an example look here.
private static StaticBean staticBean;
public void setStaticBean(StaticBean staticBean) {
StaticBean.staticBean = staticBean;
}
You should aim to use spring injection where possible as this is the recommended approach but this is not always possible as I'm sure you can imagine as not everything can be pulled from the spring container or you maybe dealing with legacy systems.
Note testing can also be more difficult with this approach.
You can use ApplicationContextAware
#Component
public class AppContext implements ApplicationContextAware{
public static ApplicationContext applicationContext;
public AppBeans(){
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
then
static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);
Disclaimer This is by no means standard and there could very well be a better spring way of doing this. None of the above answers address the issues of wiring a public static field.
I wanted to accomplish three things.
Use spring to "Autowire" (Im using #Value)
Expose a public static value
Prevent modification
My object looks like this
private static String BRANCH = "testBranch";
#Value("${content.client.branch}")
public void finalSetBranch(String branch) {
BRANCH = branch;
}
public static String BRANCH() {
return BRANCH;
}
We have checked off 1 & 2 already now how do we prevent calls to the setter, since we cannot hide it.
#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;
}
}
This aspect will wrap all methods beginning with final and throw an error if they are called.
I dont think this is particularly useful, but if you are ocd and like to keep you peas and carrots separated this is one way to do it safely.
Important Spring does not call your aspects when it calls a function. Made this easier, to bad I worked out the logic before figuring that out.
Generally, setting static field by object instance is a bad practice.
to avoid optional issues you can add synchronized definition, and set it only if private static Logger logger;
#Autowired
public synchronized void setLogger(Logger logger)
{
if (MyClass.logger == null)
{
MyClass.logger = logger;
}
}
:
Solution 1 : Using Constructor #Autowired For Static Field
#Component
public class MyClass {
private static MyService service;
#Autowired
public MyClass(MyService service) {
TestClass.service= service;
}
}
Solution 2 : Using #PostConstruct to set the value to Static Field
#Component
public class MyClass {
private static MyService service;
#Autowired
private MyService srv;
#PostConstruct
public void init() {
this.service= srv;
}
}
Refer here for more detail
I use private static inner Component: FieldSetter, to inject static field: MyBean, at last SelfDestroyBean will help me remove redundant FiledSetter bean
public final class MyClass {
private static MyBean myBean;
#Component
private static class FieldSetter extends SelfDestroyBean {
public FieldSetter(MyBean myBean) {
MyClass.myBean = myBean;
}
}
}
#SuppressWarnings("SpringJavaAutowiredMembersInspection")
public abstract class SelfDestroyBean {
#Autowired
private ApplicationContext context;
#PostConstruct
public void destroy() {
final String[] beanNames = context.getBeanNamesForType(this.getClass());
final BeanDefinitionRegistry registry =
((BeanDefinitionRegistry) context.getAutowireCapableBeanFactory());
for (String beanName : beanNames) {
registry.removeBeanDefinition(beanName);
}
}
}
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);
Is there some way to use #Autowired with static fields. If not, are there some other ways to do this?
In short, no. You cannot autowire or manually wire static fields in Spring. You'll have to write your own logic to do this.
#Component("NewClass")
public class NewClass{
private static SomeThing someThing;
#Autowired
public void setSomeThing(SomeThing someThing){
NewClass.someThing = someThing;
}
}
#Autowired can be used with setters so you could have a setter modifying an static field.
Just one final suggestion... DON'T
Init your autowired component in #PostConstruct method
#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();
}
}
Create a bean which you can autowire which will initialize the static variable as a side effect.
Wanted to add to answers that auto wiring static field (or constant) will be ignored, but also won't create any error:
#Autowired
private static String staticField = "staticValue";
You can achieve this using XML notation and the MethodInvokingFactoryBean. For an example look here.
private static StaticBean staticBean;
public void setStaticBean(StaticBean staticBean) {
StaticBean.staticBean = staticBean;
}
You should aim to use spring injection where possible as this is the recommended approach but this is not always possible as I'm sure you can imagine as not everything can be pulled from the spring container or you maybe dealing with legacy systems.
Note testing can also be more difficult with this approach.
You can use ApplicationContextAware
#Component
public class AppContext implements ApplicationContextAware{
public static ApplicationContext applicationContext;
public AppBeans(){
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
then
static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);
Disclaimer This is by no means standard and there could very well be a better spring way of doing this. None of the above answers address the issues of wiring a public static field.
I wanted to accomplish three things.
Use spring to "Autowire" (Im using #Value)
Expose a public static value
Prevent modification
My object looks like this
private static String BRANCH = "testBranch";
#Value("${content.client.branch}")
public void finalSetBranch(String branch) {
BRANCH = branch;
}
public static String BRANCH() {
return BRANCH;
}
We have checked off 1 & 2 already now how do we prevent calls to the setter, since we cannot hide it.
#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;
}
}
This aspect will wrap all methods beginning with final and throw an error if they are called.
I dont think this is particularly useful, but if you are ocd and like to keep you peas and carrots separated this is one way to do it safely.
Important Spring does not call your aspects when it calls a function. Made this easier, to bad I worked out the logic before figuring that out.
Generally, setting static field by object instance is a bad practice.
to avoid optional issues you can add synchronized definition, and set it only if private static Logger logger;
#Autowired
public synchronized void setLogger(Logger logger)
{
if (MyClass.logger == null)
{
MyClass.logger = logger;
}
}
:
Solution 1 : Using Constructor #Autowired For Static Field
#Component
public class MyClass {
private static MyService service;
#Autowired
public MyClass(MyService service) {
TestClass.service= service;
}
}
Solution 2 : Using #PostConstruct to set the value to Static Field
#Component
public class MyClass {
private static MyService service;
#Autowired
private MyService srv;
#PostConstruct
public void init() {
this.service= srv;
}
}
Refer here for more detail
I use private static inner Component: FieldSetter, to inject static field: MyBean, at last SelfDestroyBean will help me remove redundant FiledSetter bean
public final class MyClass {
private static MyBean myBean;
#Component
private static class FieldSetter extends SelfDestroyBean {
public FieldSetter(MyBean myBean) {
MyClass.myBean = myBean;
}
}
}
#SuppressWarnings("SpringJavaAutowiredMembersInspection")
public abstract class SelfDestroyBean {
#Autowired
private ApplicationContext context;
#PostConstruct
public void destroy() {
final String[] beanNames = context.getBeanNamesForType(this.getClass());
final BeanDefinitionRegistry registry =
((BeanDefinitionRegistry) context.getAutowireCapableBeanFactory());
for (String beanName : beanNames) {
registry.removeBeanDefinition(beanName);
}
}
}
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);
I have problem with injecting bean with generic types. Look at the example. I will inject to the service a repository which types takes from App class. Now i have exception:
No qualifying bean of type 'asd.IRepository' available: expected single matching bean but found 2: a,b
asd here is package, just for tests.
What can I do in this situation? Is any way to makes it?
public interface IRepository<T, V> {
void print();
}
#Component
public class A implements IRepository<String,String> {
#Override
public void print() {
System.out.println("A");
}
}
#Component
public class B implements IRepository<Double,String> {
#Override
public void print() {
System.out.println("A");
}
}
#Service
public class ServiceABC<V, T> {
#Autowired
private IRepository<V,T> repo;
public void print(){
repo.print();
}
}
#Controller
public class App {
#Autowired
private ServiceABC<String, String> serviceABC;
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext("asd");
App app = ctx.getBean(App.class);
app.serviceABC.print();
}
It looks like you don't know in advance which implementation of your IRepository interface you will need. And you will know that at runtime. In this case it is a typical case for Factory pattern where you will have a IRepositoryFactory that will have a method thhat retrieves specific implementation by type (for example IRepositoryFactory.getInstance(String type); So in your ServiceABC you may use the IRepository to get specific bean at runtime. So Factory pattern may be an answer to your question. I also wrote an article that deals with this type of problem and proposes the idea of self-populating Factory (using Open source library that provides such utility). Here is the link to the article: Non-intrusive access to "Orphaned" Beans in Spring framework
You have to name your components and autowire by name:
#Component("A")
public class A implements IRepository<String,String> {...}
#Component("B")
public class B implements IRepository<Double,String> {...}
[...]
#Autowired
#Qualifier("B")
private IRepository repo;
Something like that?
#Controller
public class RepositoryFactory {
#Autowired
private IRepository<String, String> a;
#Autowired
private IRepository<Double, String> b;
public IRepository getRepository(String className) {
if(className.equalsIgnoreCase("a")) {
return a;
} else if(className.equalsIgnoreCase("b")) {
return b;
}
return null;
}
}
#Service
public class ServiceABC {
#Autowired
private RepositoryFactory repositoryFactory;
public void print(String className){
repositoryFactory.getRepository(className).print();
}
}
#Controller
public class App {
#Autowired
private ServiceABC serviceABC;
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext("asd");
App app = ctx.getBean(App.class);
app.serviceABC.print(A.class.getSimpleName());
}
}s
I have a bean as below,
#Component
public class SpringContextUtil implements ApplicationContextAware {
private static ApplicationContext context = null;
#Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.context = applicationContext;
}
public static <T> T getBean(String beanName) {
return (T) context.getBean(beanName);
}
public static String getActiveProfile() {
return context.getEnvironment().getActiveProfiles()[0];
}
}
it is used by a plain class,
public class ConfigUtil
{
static{
String env = SpringContextUtil.getActiveProfile();
...
}
public static getVal(String key){...}
}
If the Spring Bean SpringContextUtil is initialized after the plain class ConfigUtil, then it is not OK.
So I want to know how Spring decide which one is initilialized earlier? For example, will the invocation of SpringContextUtil.getActiveProfile() trigger the initialization of the Spring bean? or the Spring Bean is only initialized but havn't been injected applicationContext yet, thus leads to a Null Pointer Exeception?
You just need to run your code after spring has been initialized.
If you're using spring-boot, create new bean that implements ApplicationListener<ApplicationReadyEvent> and run your code inside the onApplicationEvent method.
Example
#Component
public class ApplicationListenerBean implements ApplicationListener<ApplicationReadyEvent> {
#Override
public void onApplicationEvent(ApplicationReadyEvent applicationReadyEvent) {
ConfigUtil.getVal("A");
}
}
However if you want to make ConfigUtil also as a spring bean you need to get rid of static initialization block and use instead #PostConstruct annotation on your init method.
Example
#Component
#DependsOn("springContextUtil")
public class ConfigUtil {
private String env;
#PostConstruct
private void init() {
env = SpringContextUtil.getActiveProfile();
}
public static void getVal(String key) {
System.out.print("Hello");
}
}
Is there some way to use #Autowired with static fields. If not, are there some other ways to do this?
In short, no. You cannot autowire or manually wire static fields in Spring. You'll have to write your own logic to do this.
#Component("NewClass")
public class NewClass{
private static SomeThing someThing;
#Autowired
public void setSomeThing(SomeThing someThing){
NewClass.someThing = someThing;
}
}
#Autowired can be used with setters so you could have a setter modifying an static field.
Just one final suggestion... DON'T
Init your autowired component in #PostConstruct method
#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();
}
}
Create a bean which you can autowire which will initialize the static variable as a side effect.
Wanted to add to answers that auto wiring static field (or constant) will be ignored, but also won't create any error:
#Autowired
private static String staticField = "staticValue";
You can achieve this using XML notation and the MethodInvokingFactoryBean. For an example look here.
private static StaticBean staticBean;
public void setStaticBean(StaticBean staticBean) {
StaticBean.staticBean = staticBean;
}
You should aim to use spring injection where possible as this is the recommended approach but this is not always possible as I'm sure you can imagine as not everything can be pulled from the spring container or you maybe dealing with legacy systems.
Note testing can also be more difficult with this approach.
You can use ApplicationContextAware
#Component
public class AppContext implements ApplicationContextAware{
public static ApplicationContext applicationContext;
public AppBeans(){
}
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
then
static ABean bean = AppContext.applicationContext.getBean("aBean",ABean.class);
Disclaimer This is by no means standard and there could very well be a better spring way of doing this. None of the above answers address the issues of wiring a public static field.
I wanted to accomplish three things.
Use spring to "Autowire" (Im using #Value)
Expose a public static value
Prevent modification
My object looks like this
private static String BRANCH = "testBranch";
#Value("${content.client.branch}")
public void finalSetBranch(String branch) {
BRANCH = branch;
}
public static String BRANCH() {
return BRANCH;
}
We have checked off 1 & 2 already now how do we prevent calls to the setter, since we cannot hide it.
#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;
}
}
This aspect will wrap all methods beginning with final and throw an error if they are called.
I dont think this is particularly useful, but if you are ocd and like to keep you peas and carrots separated this is one way to do it safely.
Important Spring does not call your aspects when it calls a function. Made this easier, to bad I worked out the logic before figuring that out.
Generally, setting static field by object instance is a bad practice.
to avoid optional issues you can add synchronized definition, and set it only if private static Logger logger;
#Autowired
public synchronized void setLogger(Logger logger)
{
if (MyClass.logger == null)
{
MyClass.logger = logger;
}
}
:
Solution 1 : Using Constructor #Autowired For Static Field
#Component
public class MyClass {
private static MyService service;
#Autowired
public MyClass(MyService service) {
TestClass.service= service;
}
}
Solution 2 : Using #PostConstruct to set the value to Static Field
#Component
public class MyClass {
private static MyService service;
#Autowired
private MyService srv;
#PostConstruct
public void init() {
this.service= srv;
}
}
Refer here for more detail
I use private static inner Component: FieldSetter, to inject static field: MyBean, at last SelfDestroyBean will help me remove redundant FiledSetter bean
public final class MyClass {
private static MyBean myBean;
#Component
private static class FieldSetter extends SelfDestroyBean {
public FieldSetter(MyBean myBean) {
MyClass.myBean = myBean;
}
}
}
#SuppressWarnings("SpringJavaAutowiredMembersInspection")
public abstract class SelfDestroyBean {
#Autowired
private ApplicationContext context;
#PostConstruct
public void destroy() {
final String[] beanNames = context.getBeanNamesForType(this.getClass());
final BeanDefinitionRegistry registry =
((BeanDefinitionRegistry) context.getAutowireCapableBeanFactory());
for (String beanName : beanNames) {
registry.removeBeanDefinition(beanName);
}
}
}
private static UserService userService = ApplicationContextHolder.getContext().getBean(UserService.class);