2016-03-28 7 views
0

J'ai un objet de données (avec getters \ poseur seulement) qui doit être au courant du profil de printemps, à savoirJava Spring - comment injecter @Value à un objet de données?

@Value("${spring.profiles.active}") 
private String profile; 

J'ai ajouté une logique à l'un de ses méthode « set » qui vérifie le profil, à savoir

public void setItem(Item msg) { 
    if (environmentProperties.isDevMode()) { 
     this.msg= msg; 
    } 
} 

puisque cette classe est souvent maréchal \ unmarhsalled extérieur, donc, bien sûr, la @Value n'est pas peuplée - sinus Je n'ai pas utilisé le printemps autowire pour créer l'instance de classe ... I Tried défini la class comme composant, et autowire à une classe externe qui contient le profil @Value - mais cela ne fonctionne pas J'utilise le printemps 3.2 - sans définition XML.

des suggestions?

b.t. que les objets de données souvent enveloppés dans une classe d'exception - ainsi quand il est créé le profil devrait également être connu à l'objet de données ...

merci!

ÉDITÉE:

  • utilisant ApplicationContextAware ne fonctionne pas - je reçois null la méthode 'setApplicationContext' est jamais invoqué.
  • également en essayant d'obtenir le contexte directement ne fonctionne pas - obtenir null à la place lors de l'utilisation: 'ApplicationContext ctx = ContextLoader.getCurrentWebApplicationContext();'

FIXE: J'ai finalement trouvé un exemple comment accéder au contexte staticly d'une classe externe:

@Configuration 
public class ApplicationContextContainer implements ApplicationContextAware { 

    private static ApplicationContext CONTEXT; 

    /** 
    * This method is called from within the ApplicationContext once it is 
    * done starting up, it will stick a reference to itself into this bean. 
    * 
    * @param context a reference to the ApplicationContext. 
    */ 
    @Override 
    public void setApplicationContext(ApplicationContext context) throws BeansException { 
     CONTEXT = context; 
    } 

    /** 
    * This is about the same as context.getBean("beanName"), except it has its 
    * own static handle to the Spring context, so calling this method statically 
    * will give access to the beans by name in the Spring application context. 
    * As in the context.getBean("beanName") call, the caller must cast to the 
    * appropriate target class. If the bean does not exist, then a Runtime error 
    * will be thrown. 
    * 
    * @param beanName the name of the bean to get. 
    * @return an Object reference to the named bean. 
    */ 
    public static Object getBean(String beanName) { 
     return CONTEXT.getBean(beanName); 
    } 
+0

Avez-vous essayé @DependsOn ('yourPropertiesBeanName')? – Daniel

Répondre

0

Si je vous comprends bien, vous voulez injecter dans les objets non gérés par Spring, mais créé par un autre code qui appelle en interne new et renvoie des objets par exemple un cadre de sérialisation.

Pour injecter des objets non gérés, vous devrez configurer le temps de chargement ou de tissage à la compilation. Le tissage en temps de chargement nécessite un argument agent et lib lorsque vous démarrez votre machine virtuelle, certains conteneurs peuvent le faire pour vous.

Le tissage à la compilation nécessite l'utilisation du compilateur AspectJ.

Ci-dessous vous trouverez un exemple complet en utilisant Maven et Spring-Boot:

Par ex exécuter avec:

mvn spring-boot:run -Drun.arguments="--spring.profiles.active=dev" 

DemoApplication.java:

package com.example; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Configurable; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.aspectj.EnableSpringConfigured; 
import org.springframework.stereotype.Component; 

@SpringBootApplication 
public class DemoApplication { 
    @EnableSpringConfigured 
    @ComponentScan("com.example") 
    public static class AppConfiguration { 
     @Value("${spring.profiles.active}") 
     String profile; 

     @Bean 
     public String profile() { 
      return profile; 
     } 
    } 

    @Configurable 
    public static class SomePojo { 
     @Autowired 
     private String profile; 

     public void print() { 
      System.out.println(this + "\t" + profile); 
     } 
    } 

    @Component 
    public static class Runner { 
     public void run() { 
      new SomePojo().print(); 
      new SomePojo().print(); 
     } 
    } 

    public static void main(String[] args) { 
     SpringApplication.run(DemoApplication.class, args).getBean(Runner.class).run(); 
    } 

} 

pom.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
    <modelVersion>4.0.0</modelVersion> 
    <groupId>com.example</groupId> 
    <artifactId>demo</artifactId> 
    <version>0.0.1-SNAPSHOT</version> 
    <packaging>jar</packaging> 
    <name>demo</name> 
    <description>Demo project for Spring Boot</description> 
    <parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.3.3.RELEASE</version> 
     <relativePath /> <!-- lookup parent from repository --> 
    </parent> 
    <properties> 
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
     <java.version>1.8</java.version> 
    </properties> 
    <dependencies> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-aspects</artifactId> 
     </dependency> 
     <dependency> 
      <groupId>org.springframework</groupId> 
      <artifactId>spring-tx</artifactId> 
     </dependency> 
    </dependencies> 

    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.codehaus.mojo</groupId> 
       <artifactId>aspectj-maven-plugin</artifactId> 
       <version>1.8</version> 
       <configuration> 
        <complianceLevel>1.8</complianceLevel> 
        <aspectLibraries> 
         <aspectLibrary> 
          <groupId>org.springframework</groupId> 
          <artifactId>spring-aspects</artifactId> 
         </aspectLibrary> 
        </aspectLibraries> 
       </configuration> 
       <executions> 
        <execution> 
         <id>compile</id> 
         <goals> 
          <goal>compile</goal> 
         </goals> 
        </execution> 
       </executions> 
      </plugin> 
      <plugin> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-maven-plugin</artifactId> 
      </plugin> 
     </plugins> 
    </build> 
</project> 
0

D'après votre description, vous essayez d'injecter la propriété dans POJO, qui est utilisé en marshalling. Avec cette structure, vous pouvez rechercher différentes solutions de contournement avec des solutions statiques/autres complexes.

Je suggère de séparer le bean qui est utilisé comme POJO de la logique qui dépend de la valeur de la propriété. Vous pouvez extraire cette logique vers BeanService (qui peut être placé dans le contexte Spring) et la gérer à ce niveau, afin de séparer la responsabilité entre les couches Service et Data.

0

Vous vous trompez. Votre code n'a pas besoin d'être conscient du profil. Dans votre exemple, créez une interface de message et un certain nombre d'implémentations de bean de cette interface, une pour chaque profil, chacune contenant un message approprié pour ce profil, et attribuez-les à un profil afin que le bean soit instancié pour ce profil, et injectez l'instance dans la classe qui a besoin du message.

Ainsi,

public interface Message { String getMessage(); } 

@Profile("dev") @Component 
public class DevMessage implements Message { 
    public String getMessage() { return "this is the dev message"; } 
} 

@Profile("prod") @Component 
public class ProdMessage implements Message { 
    public String getMessage() { return "this is the production message"; } 
} 

Si vous préférez décrire vos haricots dans votre classe @Configuration, vous pouvez marquer une configuration complète avec un @Profile, et ont de multiples configurations.

Si vous injectez l'instance de message dans une classe, vous pouvez l'appeler getMessage(). Le profil garantit que vous disposez de la mise en œuvre appropriée pour votre environnement.

Editer: Je viens de relire votre question et j'ai réalisé que j'avais tort. Vous avez des objets d'entité stockés en dehors de l'application et instanciés via un code/framework. Ce ne sont pas des composants de ressort, et ne peuvent donc pas utiliser l'approche du ressort pour l'injection de dépendance. Dans ce cas, n'utilisez pas de ressort pour eux - cela ne fonctionne pas, n'a pas besoin de travailler et ne devrait pas fonctionner. Si vous n'avez pas instancié l'objet au printemps, alors cela ne devrait rien avoir à voir avec le printemps. Je ne connais pas votre domaine de problème, mais j'utilise le printemps depuis qu'il a été inventé et n'a jamais eu à le faire.