복붙노트

[SPRING] Java 구성에서 Spring 동적 언어 지원 사용

SPRING

Java 구성에서 Spring 동적 언어 지원 사용

스프링 프레임 워크의 동적 언어 지원을 사용하고 싶습니다.

XML에서는 lang 네임 스페이스를 사용하고 싶지만 Java 구성 (즉, @Configuration 클래스) 만 사용하고 싶습니다.

org.springframework.scripting.config 패키지, inc에서 지옥을 초기화하여이 작업을 수행 할 수 있다고 상상할 수 있습니다. BeanPostProcessors, Handlers, Parsers 및 FactoryBeans를 생성하지만 실제로 거기에 가지 않기를 원합니다.

다른 방법이 있습니까? 없으면 Groovy 스크립트에서 재로드 가능한 빈을 작성하는 데 필요한 최소한의 구성은 무엇입니까?

해결법

  1. ==============================

    1.왜 우리에게 이메일로 직접 물어 보지 않으시겠습니까? :-)

    왜 우리에게 이메일로 직접 물어 보지 않으시겠습니까? :-)

    나는 XML Lang 지원이 마술이라는 것을 알았다. BeanDefinition과 그 속성에 기반을 둔 물건이 충분합니다. 추가로 lang : 속성에 대한 ProxyFactory 및 CGLIB와의 연결 고리가 있습니다.

    JavaConfig에서 볼 수있는 것은 Spring Integration의 ScriptEvaluator 및 RefreshableResourceScriptSource 용 Java 클래스 래퍼입니다.

    @ContextConfiguration
    @RunWith(SpringJUnit4ClassRunner.class)
    public class RefreshableScriptJavaConfigTests {
    
        @Autowired
        private Calculator calculator;
    
        @Test
        public void testGroovyRefreshableCalculator() {
            assertEquals(5, this.calculator.add(2, 3));
        }
    
        @Configuration
        public static class ContextConfiguration {
    
            @Value("classpath:org/springframework/integration/scripting/config/jsr223/Calculator.groovy")
            private Resource groovyScriptResource;
    
            @Bean
            public ScriptEvaluator groovyScriptEvaluator() {
                return new GroovyScriptEvaluator();
            }
    
            @Bean
            public Calculator calculator() {
                return new Calculator(new RefreshableResourceScriptSource(this.groovyScriptResource, 1000));
            }
    
        }
    
        public static class Calculator {
    
            private final ScriptSource scriptSource;
    
            @Autowired
            private ScriptEvaluator scriptEvaluator;
    
            public Calculator(ScriptSource scriptSource) {
                this.scriptSource = scriptSource;
            }
    
            public int add(int x, int y) {
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("x", x);
                params.put("y", y);
                return (int) this.scriptEvaluator.evaluate(this.scriptSource, params);
            }
    
        }
    
    }
    

    Calculator.groovy의 위치 :

    x + y
    

    XML 정의에서 인터페이스 및 구성으로 보이는 것처럼 유연하지는 않지만 적어도 그것이 어디에 있는지 알 수 있도록 도와줍니다.

    이 문제에 대해 JIRA 문제를 제기 해 주시면 우리가 여기서 할 수있는 것을 보게 될 것입니다. Resource @Bean 메소드에서 @EnableScripting 및 @ScriptSource (refreshDelay = 1000)와 같은 것입니다.

    지금 당장 당신은 @lang 정의를 가진 XML 조각을 @ import 할 수 있다고 생각합니다.

    건배, 아르템

  2. ==============================

    2.나는 동일한 경로 (진행중인 작업)로 진행할 것이고 Spring 애플리케이션이 준비 될 때 bean 정의를 추가함으로써 재로드 가능한 Groovy 스크립트를 초기화 할 수있다. 제 예제에서는 스프링 부트를 사용하고 있습니다.

    나는 동일한 경로 (진행중인 작업)로 진행할 것이고 Spring 애플리케이션이 준비 될 때 bean 정의를 추가함으로써 재로드 가능한 Groovy 스크립트를 초기화 할 수있다. 제 예제에서는 스프링 부트를 사용하고 있습니다.

    다음 AddBeanDefinitionsListener 리스너 클래스와 ScriptFactoryPostProcessor 빈을 추가하면 아주 적은 노력으로 Groovy 스크립트를 초기화 할 수 있습니다.

    AddBeanDefinitionsListener.groovy

    public class AddBeanDefinitionsListener 
            implements ApplicationListener<ApplicationPreparedEvent> {
    
        Map<String, BeanDefinition> beanDefs
    
        AddBeanDefinitionsListener(Map<String, BeanDefinition> beanDefs) {
            this.beanDefs = beanDefs
        }
    
        @Override
        void onApplicationEvent(ApplicationPreparedEvent event) {
            def registry = (BeanDefinitionRegistry) event.applicationContext
                    .autowireCapableBeanFactory
            beanDefs.each { String beanName, BeanDefinition beanDef ->
                registry.registerBeanDefinition(beanName, beanDef)
            }
        }
    
        /* Static Utility methods */
    
        static BeanDefinition groovyScriptFactory(String scriptLocation) {
            def bd = BeanDefinitionBuilder.genericBeanDefinition(GroovyScriptFactory)
                    .addConstructorArgValue(scriptLocation)
                    .getBeanDefinition()
            bd.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, 1000)
            bd
        }
    
    }
    

    Application.groovy

    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            SpringApplication app = new SpringApplication(Application)
            app.addListeners(new AddBeanDefinitionsListener([
                    'foobar0': groovyScriptFactory("file:/some/path/Foobar0Service.groovy"),
                    'foobar1': groovyScriptFactory("file:/some/path/Foobar1Service.groovy")
            ]))
            app.run(args)
        }
    
        @Bean
        ScriptFactoryPostProcessor scriptFactory() {
            new ScriptFactoryPostProcessor()
        }
    
    }
    

    (Spring 4.2의 이벤트로 구현한다면 더 좋을지도 모른다.)

  3. from https://stackoverflow.com/questions/26208020/using-spring-dynamic-languages-support-from-java-configuration by cc-by-sa and MIT license