Setting the Spring bean Class Name Using SpEL Expression and PropertyPlaceHolder

UPDATED: Summary of Resolution of 12/9/2016

According to @altazar below, now it's possible from Spring 4.2!

Summary of the old permission from 3/29/2012

From this date, Spring SpEL cannot execute inside the class <bean> attribute.

The original question:

I am trying to implement a dynamic class attribute for a Spring bean, ultimately set using a combination of the PropertyPlaceHolder and the SpEL expression. The goal is either the release or debug version of the class to instantiate. It does not work, and I wonder if it can be achieved.

So far I have the following:

Flat properties file :

 is.debug.mode=false 

Spring XML Configuration :

 <bean id="example" class="#{ ${is.debug.mode} ? com.springtest.ExampleDebug : com.springtest.ExampleProd}" /> 

Spring Java boot code :

  // Get basic ApplicationContext - DO NOT REFRESH FileSystemXmlApplicationContext applicationContext = new FileSystemXmlApplicationContext (new String[] {pathSpringConfig}, false); // Load properties ResourceLoader resourceLoader = new DefaultResourceLoader (); Resource resource = resourceLoader.getResource("file:" + pathProperties); Properties properties = new Properties(); properties.load(resource.getInputStream()); // Link to ApplicationContext PropertyPlaceholderConfigurer propertyConfigurer = new PropertyPlaceholderConfigurer() ; propertyConfigurer.setProperties(properties) ; applicationContext.addBeanFactoryPostProcessor(propertyConfigurer); // Refresh - load beans applicationContext.refresh(); // Done Example example = (Example) applicationContext.getBean("example"); 

Error message (for clarity, many spaces removed) :

 Caused by: java.lang.ClassNotFoundException: #{ true ? com.springtest.ExampleDebug : com.springtest.ExampleProd} at java.net.URLClassLoader$1.run(URLClassLoader.java:366) at java.net.URLClassLoader$1.run(URLClassLoader.java:355) . . . 

As you see in the " true " message, the is.debug.mode property has is.debug.mode successfully loaded and replaced. But something else is going wrong. Is this my bootstrap in Java? Or the SPeL syntax in XML? Or another problem?

BTW I am aware of the new profile feature 3.1, but I would like to do it through SPeL for various reasons. I also understand that I use a file system based context and path. I also have reasons for this.

+4
source share
3 answers

You can accomplish what you intend with factoryBean:

 <bean id="example" class="MyFactoryBean"> <property name="class" value="#{ ${is.debug.mode} ? com.springtest.ExampleDebug : com.springtest.ExampleProd}"/> </bean> 

where MyFactoryBean is a trivial instance of a FactoryBean instance that returns the specified class.

+4
source

You can do it.

 debug.class=com.springtest.ExampleDebug #debug.class=com.springtest.ExampleProd 

and then

 <bean id="example" class="${debug.class}"/> 
+2
source

From Spring 4.2, it can be used to use the SpEl attribute in a class, so the following works well:

 <bean id="example" class="#{T(java.lang.Boolean).parseBoolean('${is.debug.mode:false}') ? 'com.springtest.ExampleDebug' : 'com.springtest.ExampleProd'}"/> 

In my case, placeholder ${is.debug.mode:false} did not work, so I parse it explicitly.

+2
source

Source: https://habr.com/ru/post/1403894/


All Articles