132 votes

@Autowired et méthode statique

J'ai @Autowired qui doit être utilisé à l'intérieur d'une méthode statique. Je sais que ce n'est pas correct mais je ne peux pas changer la conception actuelle car cela nécessiterait beaucoup de travail, j'ai donc besoin d'un hack simple pour cela. Je ne peux pas modifier randomMethod() pour être non-statique et j'ai besoin d'utiliser ce bean autowired. Avez-vous une idée de la façon de procéder ?

@Service
public class Foo {
    public int doStuff() {
        return 1;
    }
}

public class Boo {
    @Autowired
    Foo foo;

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

187voto

Francisco Spaeth Points 10069

Vous pouvez le faire en suivant l'une des solutions :

Utilisation du constructeur @Autowired

Cette approche construira le bean en exigeant certains beans comme paramètres du constructeur. Dans le code du constructeur, vous définissez le champ statique avec la valeur obtenue comme paramètre pour l'exécution du constructeur. Exemple :

@Component
public class Boo {

    private static Foo foo;

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

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

Utilisation de @PostConstruct pour transmettre une valeur à un champ statique

L'idée ici est de transférer un bean vers un champ statique après que le bean ait été configuré par Spring.

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

53voto

Pavel Horal Points 5801

Vous devez contourner ce problème en utilisant l'approche de l'accesseur de contexte d'application statique :

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

}

Vous pouvez alors accéder aux instances de haricots de manière statique.

public class Boo {

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

}

11voto

Sotirios Delimanolis Points 77933

Ce que vous pouvez faire, c'est @Autowired une méthode setter et lui faire définir un nouveau champ statique.

public class Boo {
    @Autowired
    Foo foo;

    static Foo staticFoo;   

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

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

Lorsque le bean sera traité, Spring injectera un fichier Foo dans le champ "instance". foo . Il injectera alors également le même Foo dans le setStaticFoo() liste d'arguments, qui sera utilisée pour définir le champ statique.

Il s'agit d'une mauvaise solution de contournement et elle échouera si vous essayez d'utiliser l'option randomMethod() avant que Spring n'ait traité une instance de Boo .

6voto

Bludwood Points 41

La façon la plus simple de créer un contexte statique est naturellement, au démarrage de l'application. Cela évitera la nécessité d'une implémentation non naturelle avec une classe supplémentaire.

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

Ensuite, chaque fois que vous devez accéder à un bean de manière statique, vous pouvez utiliser l'ApplicationContext pour obtenir l'instance de la classe.

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

Regards

3voto

Jean-Philippe Bond Points 3872

C'est nul, mais vous pouvez obtenir le haricot en utilisant la fonction ApplicationContextAware interface. Quelque chose comme :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X