2014-05-13 2 views
5

Spring에서 사용한 환경 Bean을 자체 구현으로 대체하고자합니다. 이 나쁜 습관입니까, 그렇지 않다면 어떻게해야합니까? 현재 Environment 인터페이스를 구현하고 기존 환경 Bean을 사용하는 Bean을 만들었지 만 환경 Bean을 필요로하는 모든 구성 코드는 이제 내 사용자 정의 환경 Bean을 사용해야합니다. 스프링 환경 빈을 내 환경 변수로 대체하는 것이 더 깔끔할 것이라고 생각 하겠지만, 환경 설정을 변경할 필요가 없다. 현재이 작업을 수행 할 수있는 유일한 방법은 내 자신의 ApplicationContext를 만들어 환경을 내 자신으로 설정하거나 ApplicationContextAware가 될 환경을 설정하는 것입니다. 이 두 가지 모두 나에게 조금은 호기심이있는 것처럼 보입니다.Spring : Application Context에서 생성 된 Environment Bean을 대체하는 방법

제약 : 나는 Spring3의 최신 버전을 사용하고

  • .
  • Java 기반 구성을 사용하고 있습니다. XML이 아닙니다

고맙습니다.

편집 : 배경

가 나는 경우에 이렇게 내 생각이 결함이 원하는 내가 왜 설명해야 가정합니다. 나는 비 구조적인 "왜 그렇게하고 싶습니까?"라고 피하기 위해 이것을 피했습니다. 응답.

스프링 환경 빈은 속성 값을 찾을 때 일련의 속성 소스를 사용합니다. 전형적인 스택은 다음과 같습니다 (이에 제한되지 않음) :

  • JNDI
  • 시스템 등록 정보 (-Dmyprop = foo를 통해 설정)
  • 환경 변수
  • ...

보안상의 이유로 이러한 속성 중 일부 (예 : 데이터베이스 암호)를 암호화해야합니다. 해결책은 Jasypt를 속성 암호화에 사용하는 것입니다. 그러나 Spring/Jasypt는 새로운 속성 소스를 환경에 삽입하는 수단 만 제공합니다. 그래서 : 잠재적으로 암호화 된 값

  • JNDI
  • 시스템 속성 (-Dmyprop = foo를 통해 설정)
  • 환경 변수
    • 재산권 파일 ... 그러나

    , 이는 작업 그룹이 유지 관리 할 속성 만 단일 파일에 저장하거나 속성을 여러 파일로 분산시킬 수 있다는 점에서 이상적인 것은 아닙니다. t 속성 파일, 환경 변수 등. 또한 속성은 속성 소스와 상관없이 암호화 될 수있는 가능성이 있다고 생각합니다.

    그래서 환경에 접근하려고 시도 할 때마다 코드의 속성을 암호 해독해야하거나, 나를 위해이 환경 bean을 만들어야한다고 생각합니다.

    건설적인 개의 의견과 다른 정보를 환영합니다.

    EDIT : 추가 용액

    public class EnvironmentBeanFactoryPostProcessor implements BeanFactoryPostProcessor { 
    
        private static final String CONFIGURATION_PROPERTY_PBE_ALGORITHM = "PBE_ALGORITHM"; 
        private static final String CONFIGURATION_PROPERTY_PBE_PASSWORD = "PBE_PASSWORD"; 
    
        @Override 
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 
         StandardEnvironment environment = (StandardEnvironment) beanFactory.getBean("environment"); 
    
         if (environment != null) { 
          StringEncryptor encryptor = this.getEncryptor(environment); 
    
          MutablePropertySources mutablePropertySources = environment.getPropertySources(); 
    
          for (PropertySource<?> propertySource : mutablePropertySources) { 
           mutablePropertySources.replace(
             propertySource.getName(), 
             new EncryptablePropertySourcePropertySource(propertySource.getName(), propertySource, encryptor)); 
          } 
         } 
        } 
    
        private StringEncryptor getEncryptor(Environment environment) { 
         StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); 
    
         String algorithm = environment.getProperty(CONFIGURATION_PROPERTY_PBE_ALGORITHM); 
         if (algorithm != null) { 
          encryptor.setAlgorithm(algorithm); 
         } 
    
         String password = environment.getProperty(CONFIGURATION_PROPERTY_PBE_PASSWORD); 
         if (password != null) { 
          encryptor.setPassword(password); 
         } 
    
         return encryptor; 
        } 
    
        private class EncryptablePropertySourcePropertySource extends PropertySource<PropertySource<?>> { 
    
         private StringEncryptor stringEncryptor; 
    
         private TextEncryptor textEncryptor; 
    
         public EncryptablePropertySourcePropertySource(final String name, final PropertySource<?> propertySource, final StringEncryptor encryptor) { 
          super(name, propertySource); 
    
          this.stringEncryptor = encryptor; 
         } 
    
         public EncryptablePropertySourcePropertySource(final String name, final PropertySource<?> propertySource, final TextEncryptor encryptor) { 
          super(name, propertySource); 
    
          this.textEncryptor = encryptor; 
         } 
    
         @Override 
         public Object getProperty(String name) { 
          Object value = this.source.getProperty(name); 
    
          if (value != null && value instanceof String) { 
           value = this.decode((String) value); 
          } 
    
          return value; 
         } 
    
         private String decode(String encodedValue) { 
          if (!PropertyValueEncryptionUtils.isEncryptedValue(encodedValue)) { 
           return encodedValue; 
          } 
    
          if (this.stringEncryptor != null) { 
           return PropertyValueEncryptionUtils.decrypt(encodedValue, this.stringEncryptor); 
    
          } 
    
          if (this.textEncryptor != null) { 
           return PropertyValueEncryptionUtils.decrypt(encodedValue, this.textEncryptor); 
          } 
    
          throw new EncryptionOperationNotPossibleException(
            "Neither a string encryptor nor a text encryptor exist " 
            + "for this instance of EncryptableProperties. This is usually " 
            + "caused by the instance having been serialized and then " 
            + "de-serialized in a different classloader or virtual machine, " 
            + "which is an unsupported behaviour (as encryptors cannot be " 
            + "serialized themselves)"); 
         } 
    
        } 
    } 
    
  • +2

    표준 Spring 항목으로는 수행 할 수없는 자신의 '환경'을 롤업하여 무엇을 달성하려고합니까? – geoand

    +0

    'AbstractApplicationContext'의'setEnvironment()'메소드가 public이라는 것을 볼 수 있습니다. 그래서, 당신은'ApplicationContextAware'를 구현 한 빈을 가지고 앱 컨텍스트를 획득 할 수 있고 거기에서 당신 자신의 환경을 설정할 수 있습니다. 해보지는 않았지만 이것이 내가 시도 할 첫 번째 일이라고 생각합니다. –

    +0

    @geoand 내 편집을 참조하십시오. – loesak

    답변

    2

    M. Deinum로부터 그러나, 스프링/Jasypt 만 환경에 새로운 속성 소스를 삽입하는 수단을 제공 대답에 기초.

    실제로 어디에서 잘못 되었습니까? PropertySources도 대체 할 수 있습니다. javadocMutablePropertySources입니다. 이것은 또한 내부적으로 스프링에 의해 처음에 dummy PropertySources을 추가하고 나중에 대체하기 위해 사용됩니다.

    당신이 할 수있는 일은 PropertySource에 위임하고 그 값을 즉시 해독하는 PropertySource을 생성하는 것입니다. 그렇게하면 모든 PropertySources을 원본을 감싸는 것으로 바꿀 수 있습니다.

    MutablePropertySources mps = env.getgetPropertySources(); 
    for (PropertySource ps : env.getgetPropertySources()) { 
        EncryptablePropertySource eps = new EncryptablePropertySource(ps.getName(), ps, encryptor); 
        mps.replace(ps.getName(), eps); 
    } 
    

    당신은 샘플로 EncryptablePropertiesPropertySource을 사용할 수 있습니다, 당신이 기본적으로해야 할 것은 PropertySourceProperties을 대체합니다.

    SPR-8928을 수정하면 단순히 EncryptedPropertySourcesPlaceholderConfigurer이 등록되고 모든 속성이 변환되어 이러한 해킹이 필요하지 않으므로 더 쉽습니다.

    +0

    고맙습니다.나는 틀렸을 수도 있고 그렇게되기를 바랐다. 이것에 대해 살펴보고 올바른 길을 선택하면 적절하게 답을 표시 할 것입니다. – loesak

    +0

    나는 이것을 조사하고 있기 때문에 버그가 수정 될 때까지 이것을 수행하는 것이 적절한 방법이라고 생각합니다. 내가 알지 못하는 것은 이것이 환경을 필요로하는 어떤 콩보다 먼저 일어나는지를 확인하는 방법이다. – loesak

    +0

    BeanFactoryPostProcessor – loesak

    관련 문제