web-dev-qa-db-fra.com

Comment injecter des dépendances dans un objet auto-instancié au printemps?

Disons que nous avons un cours:

public class MyClass {
    @Autowired private AnotherBean anotherBean;
}

Ensuite, nous avons créé un objet de cette classe (ou un autre framework a créé l’instance de cette classe).

MyClass obj = new MyClass();

Est-il possible d'injecter encore les dépendances? Quelque chose comme:

applicationContext.injectDependencies(obj);

(Je pense que Google Guice a quelque chose comme ça)

117
Igor Mukhin

Vous pouvez le faire en utilisant la méthode autowireBean() de AutowireCapableBeanFactory. Vous lui transmettez un objet arbitraire et Spring le traitera comme quelque chose qu'il aurait créé lui-même et appliquera les divers éléments de l'auto-câblage.

Pour obtenir le AutowireCapableBeanFactory, il suffit d’autowire que:

private @Autowired AutowireCapableBeanFactory beanFactory;

public void doStuff() {
   MyBean obj = new MyBean();
   beanFactory.autowireBean(obj);
   // obj will now have its dependencies autowired.
}
174
skaffman

Vous pouvez également marquer votre MyClass avec une annotation @Configurable:

@Configurable
public class MyClass {
   @Autowired private AnotherClass instance
}

Ensuite, au moment de la création, il injectera automatiquement ses dépendances. Vous devriez aussi avoir <context:spring-configured/> dans votre contexte d'application xml.

18
glaz666

Je viens d'avoir le même besoin et dans mon cas, c'était déjà la logique à l'intérieur non gérable de la classe Java) qui avait accès à ApplicationContext. Inspiré par scaffman. Résolu par:

AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(manuallyCreatedInstance);
3
rand0m86

Je voulais partager ma solution qui suit l'approche @Configurable En tant que briefly mentionnée dans @ glaz666 réponse parce que

  • Le réponse de @skaffman a presque 10 ans, ce qui ne veut pas dire pas assez bon ou ça ne marche pas
  • La réponse de @ glaz666 est brève et ne m'a pas vraiment aidée à résoudre mon problème, mais elle m'a orientée dans la bonne direction.

Ma configuration

  1. Spring Boot 2.0.3 avec Spring Neo4j & Aop starts (Ce qui n’est de toute façon pas pertinent)
  2. Instanciez un bean lorsque Spring Boot Est prêt en utilisant l'approche @Configurable (En utilisant ApplicationRunner)
  3. Gradle & Eclipse

Pas

Je devais suivre les étapes ci-dessous afin de le faire fonctionner

  1. La @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false) à placer sur votre Bean à instancier manuellement. Dans mon cas, les Bean à instancier manuellement ont des services @Autowired, Par conséquent, les accessoires de l'annotation ci-dessus.
  2. Annotez le principal XXXApplicaiton.Java Du démarrage de printemps (ou le fichier annoté avec @SpringBootApplication) Avec le @EnableSpringConfigured Et la @EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
  3. Ajoutez les dépendances dans votre fichier de construction (par exemple, build.gradle ou pom.xml, en fonction de celui que vous utilisez) compile('org.springframework.boot:spring-boot-starter-aop') et compile('org.springframework:spring-aspects:5.0.7.RELEASE')
  4. Nouveau + votre Bean qui est annoté avec @Configurable N'importe où et ses dépendances devraient être automatiquement câblées.

* En ce qui concerne le point 3 ci-dessus, je suis conscient que le org.springframework.boot:spring-boot-starter-aop Tire de manière transitoire le spring-aop (Comme indiqué ici mavencentral ) mais, dans mon cas, l'Eclipse a échoué. pour résoudre les annotations @EnableSpringConfigured, par conséquent, j’ai explicitement ajouté la dépendance spring-aop en plus du démarreur. Si vous rencontrez le même problème, déclarez simplement votre dépendance ou partez à l’aventure pour comprendre

  • Y a-t-il un conflit de version
  • Pourquoi le org.springframework.context.annotation.aspect.* N'est pas disponible
  • Votre configuration IDE est-elle correcte
  • Etc.
2
Raf