@Autowired 및 정적 메서드
나는이 @Autowired
정적 메서드 내에서 사용하는 서비스입니다. 이것이 틀렸다는 것을 알고 있지만 많은 작업이 필요하기 때문에 현재 디자인을 변경할 수 없으므로 간단한 해킹이 필요합니다. randomMethod()
비 정적으로 변경할 수 없으며이 자동 연결 빈을 사용해야합니다. 그 방법에 대한 단서가 있습니까?
@Service
public class Foo {
public int doStuff() {
return 1;
}
}
public class Boo {
@Autowired
Foo foo;
public static void randomMethod() {
foo.doStuff();
}
}
솔루션 중 하나에 따라이를 수행 할 수 있습니다.
@Autowired 생성자 사용
이 접근 방식은 생성자 매개 변수로 일부 빈이 필요한 빈을 생성합니다. 생성자 코드 내에서 생성자 실행을위한 매개 변수로 얻은 값으로 정적 필드를 설정합니다. 견본:
@Component
public class Boo {
private static Foo foo;
@Autowired
public Boo(Foo foo) {
Boo.foo = foo;
}
public static void randomMethod() {
foo.doStuff();
}
}
@PostConstruct를 사용하여 값을 정적 필드에 전달
여기서 아이디어는 bean이 spring에 의해 구성된 후 정적 필드에 bean을 넘겨주는 것입니다.
@Component
public class Boo {
private static Foo foo;
@Autowired
private Foo tFoo;
@PostConstruct
public void init() {
Boo.foo = tFoo;
}
public static void randomMethod() {
foo.doStuff();
}
}
You have to workaround this via static application context accessor approach:
@Component
public class StaticContextAccessor {
private static StaticContextAccessor instance;
@Autowired
private ApplicationContext applicationContext;
@PostConstruct
public void registerInstance() {
instance = this;
}
public static <T> T getBean(Class<T> clazz) {
return instance.applicationContext.getBean(clazz);
}
}
Then you can access bean instances in a static manner.
public class Boo {
public static void randomMethod() {
StaticContextAccessor.getBean(Foo.class).doStuff();
}
}
What you can do is @Autowired
a setter method and have it set a new static field.
public class Boo {
@Autowired
Foo foo;
static Foo staticFoo;
@Autowired
public void setStaticFoo(Foo foo) {
Boo.staticFoo = foo;
}
public static void randomMethod() {
staticFoo.doStuff();
}
}
When the bean gets processed, Spring will inject a Foo
implementation instance into the instance field foo
. It will then also inject the same Foo
instance into the setStaticFoo()
argument list, which will be used to set the static field.
This is a terrible workaround and will fail if you try to use randomMethod()
before Spring has processed an instance of Boo
.
It sucks but you can get the bean by using the ApplicationContextAware
interface. Something like :
public class Boo implements ApplicationContextAware {
private static ApplicationContext appContext;
@Autowired
Foo foo;
public static void randomMethod() {
Foo fooInstance = appContext.getBean(Foo.class);
fooInstance.doStuff();
}
@Override
public void setApplicationContext(ApplicationContext appContext) {
Boo.appContext = appContext;
}
}
This builds upon @Pavel's answer, to solve the possibility of Spring context not being initialized when accessing from the static getBean method:
@Component
public class Spring {
private static final Logger LOG = LoggerFactory.getLogger (Spring.class);
private static Spring spring;
@Autowired
private ApplicationContext context;
@PostConstruct
public void registerInstance () {
spring = this;
}
private Spring (ApplicationContext context) {
this.context = context;
}
private static synchronized void initContext () {
if (spring == null) {
LOG.info ("Initializing Spring Context...");
ApplicationContext context = new AnnotationConfigApplicationContext (io.zeniq.spring.BaseConfig.class);
spring = new Spring (context);
}
}
public static <T> T getBean(String name, Class<T> className) throws BeansException {
initContext();
return spring.context.getBean(name, className);
}
public static <T> T getBean(Class<T> className) throws BeansException {
initContext();
return spring.context.getBean(className);
}
public static AutowireCapableBeanFactory getBeanFactory() throws IllegalStateException {
initContext();
return spring.context.getAutowireCapableBeanFactory ();
}
}
The important piece here is the initContext
method. It ensures that the context will always get initialized. But, do note that initContext
will be a point of contention in your code as it is synchronized. If your application is heavily parallelized (for eg: the backend of a high traffic site), this might not be a good solution for you.
Use AppContext. Make sure you create a bean in your context file.
private final static Foo foo = AppContext.getApplicationContext().getBean(Foo.class);
public static void randomMethod() {
foo.doStuff();
}
참고URL : https://stackoverflow.com/questions/17659875/autowired-and-static-method
'program story' 카테고리의 다른 글
Google Maps Android API v2를 사용하여 두 지점 사이에 경로 그리기 (0) | 2020.09.24 |
---|---|
Java에서 문자열 배열 초기화 (0) | 2020.09.24 |
Ansible로 Linux 환경 변수를 설정하는 방법 (0) | 2020.09.24 |
파이썬에서 int ()의 직관적이지 않은 동작 (0) | 2020.09.23 |
2보다 큰 MySQL 수 발생 (0) | 2020.09.23 |