programing

그리고 정적Autowired 법 @

sourcetip 2022. 9. 5. 23:32
반응형

그리고 정적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 @ 정적 필드에 손에 사용됩니다.

여기서의 생각은 후에 콩 스프링으로 구성된 정적 필드에 콩을 양도하는 것이다.

@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();
    }
}

정전기 응용 컨텍스트accessor 접근법을 통해 이 workaround에 갖게 된다.

@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);
    }

}

그리고는 정적 방식으로 콩 인스턴스에 액세스 할 수 있다.

public class Boo {

    public static void randomMethod() {
         StaticContextAccessor.getBean(Foo.class).doStuff();
    }

}

할 수 있는 건@Autowiredsetter 메서드를 사용하여 새로운 정적 필드를 설정합니다.

public class Boo {
    @Autowired
    Foo foo;

    static Foo staticFoo;   

    @Autowired
    public void setStaticFoo(Foo foo) {
        Boo.staticFoo = foo;
    }

    public static void randomMethod() {
         staticFoo.doStuff();
    }
}

콩이 가공되면, 스프링이 주사할 것입니다.Foo인스턴스 필드에 구현 인스턴스foo그런 다음 같은 것을 주입합니다.Foo에 인스턴스하다.setStaticFoo()static 필드를 설정하기 위해 사용됩니다.

이는 끔찍한 회피책이며, 이 방법을 사용하려고 하면 실패합니다.randomMethod()봄이 지나기 전에Boo.

스태틱 콘텍스트를 작성하는 가장 쉬운 방법은 응용 프로그램을 시작할 때 자연스럽게 작성하는 것입니다.이것에 의해, 추가 클래스의 부자연스러운 실장이 불필요하게 되는 것을 막을 수 있습니다.

@SpringBootApplication
public class MyApplication {

    private static ApplicationContext appContext;


    public static void main(String[] args) {
        appContext = SpringApplication.run(MyApplication.class, args);
    }

    public static ApplicationContext getAppContext() {
        return appContext;
    }
}

그런 다음 Bean에 정적으로 액세스해야 하는 모든 위치에서 ApplicationContext를 사용하여 클래스의 인스턴스를 가져올 수 있습니다.

public class Boo {
    public static void randomMethod() {
         MyApplication.getAppContext()
                            .getBean(Foo.class).doStuff();
    }
}

잘 부탁드립니다.

구린내 나는데 콩을 구하려면ApplicationContextAware인터페이스입니다.예를 들어 다음과 같습니다.

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;
    }
}

이는 정적 getBean 메서드에서 액세스할 때 스프링 컨텍스트가 초기화되지 않을 가능성을 해결하기 위해 @Pavel의 답변을 기반으로 합니다.

@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 ();
  }
}

여기서 중요한 건initContext방법.그러면 컨텍스트가 항상 초기화됩니다.단, 주의해 주십시오.initContext동기화할 때 코드의 경합 포인트가 됩니다.애플리케이션이 고도로 병렬화되어 있는 경우(예를 들어 트래픽이 많은 사이트의 백엔드)에는 이 솔루션이 적합하지 않을 수 있습니다.

AppContext를 사용합니다.컨텍스트 파일에 빈을 작성해야 합니다.

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

반응형