Spring Property Injection with Play2 Framework - java

I like many features of Play Framework 2 (I'm using it with Java) but, as a fan of Dependency Injection, I love also Spring and particularly, its way to inject configuration into objects by just using the #Value annotation.
Therefore, I would love to know how to inject into an instance variable the value of a property using Play's built-in property resolution mechanism. Something like this:
#Component
public class SpringBeanWithinAPlay2Application {
#Value("${application.timeout:10}")
private int timeout;
}
Any clue anyone?
Many thanks in advance.

I had the same problem a while ago and this was my way of making this work:
Firstly, when you boostrap your Spring Application context (I use annotation based configuration but the same should work for XML based), you have to add a custom PropertySource, which is the way Spring enables the addition of new way of resolving properties. Something like this:
public static void initialize() {
ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().getPropertySources().addFirst(new PlayFrameworkPropertySource());
ctx.scan("somepackage");
ctx.refresh();
}
The custom class PlayFrameworkPropertySource is the one that does the magic:
public class PlayFrameworkPropertySource extends PropertySource<Object> {
public PlayFrameworkPropertySource() {
super("Play Framework properties resolution mechanism");
}
#Override
public Object getProperty(String propertyName) {
// or ConfigFactory.load().getString(propertyName), as you prefer...
return Configuration.root().getString(propertyName);
}
}
In order for all this to work, you just need to do one more thing: explicitly declare a bean of type PropertySourcesPlaceholderConfigurer in some #Configuration class you might be using:
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Important Note: this bean must be static, as it's a BeanFactoryPostProcessor and it should be loaded prior to any other regular #Bean.
This worked like a charm for me, hope this is helpful to someone else!
Cheers,
Jonathan

Related

Create bean only if property file/xml file exists [duplicate]

Lets say i have two beans:
class MyBean implements BeanInterface(){}
class MyBean2 implements BeanInterface(){}
And if specific property exists, i want to create MyBean, otherwise I want to create MyBean2(). How can i do this?
#Bean
#ConditionalOnProperty(name = "property.validation")
public BeanInterface beanInterface() {
return new MyBean();
}
works if I want to create MyBean if property exists, but how do I create MyBean2 if it doesn't?
#Bean
#ConditionalOnMissingBean(MyBean.class)
public BeanInterface beanInterface() {
return new MyBean2();
}
complains that method with same name exists, and if i understand it correctly, the methods name need to be camelCase name of the bean.
How do i do this?
Thanks
//edit i tried:
#Bean
#ConditionalOnProperty(name = "property.validation")
#Order(1)
public BeanInterface beanInterface() {
return new MyBean();
}
#Bean("beanInterface")
#ConditionalOnMissingBean(MyBean.class)
#Order(2)
public BeanInterface beanInterface() {
return new MyBean2();
}
but it didnt work, second bean is not getting created when property is missing.
You can specify bean name #Bean("beanInterface") then method name can be anything.
You have Java configuration at your hands, so use that to your advantage. Not everything needs annotations to be fixed.
#Bean
public BeanInterface myBean(Environment env) {
String validation = env.getProperty("property.validation", String.class);
return validation != null ? new MyBean(validation) : new MyBean2();
}
The name of the method doesn't matter it can be anything you like.
Spring and Spring boot provide a a following solution: If you need to choose one implementation of the interface at runtime, than you inject all implementations and choose appropriate one at runtime. Assuming that you have an interface DataSource with multiple implementations here is how you inject them all:
#Autowired
private List<DataSource> dataSources;
You can read about this solution here.
This is a standard solution, but I really don't like it as it is waistful to inject all implementations. So, I wrote a feature that is available as part of MgntUtils open-source library. That feature allows you to create a static factory per each interface, and once you add any implementation of that interface declared as a Bean, that implementation will be added automatically at start up into a relevant factory. So, instead of injecting all implementations in your class you at runtime take from the factory needed implementation. I think it is much more elegant solution, and it has been battle-tested and it works well. Here is Javadoc that explains the concept and has a detailed example on how to use it: Lifecycle management. Also here is the article that describes this feature in detail: Non-intrusive access to "Orphaned" Beans in Spring framework. The library is available as Maven artifact at Maven central ad also on Github including javadoc and source code. In the source code there is a working example on how to use this feature

Spring Boot 2 - Do something before the beans are initialized

Problem Statement
I want to load properties from a properties file in a classpath or at an external location before the beans are initialized. These properties are also a part of Bean initialization. I cannot autowire the properties from Spring's standard application.properties or its customization because the same properties file must be accessible by multiple deployables.
What I Tried
I'm aware about Spring Application Events; in fact, I'm already hooking
ContextRefreshedEvent to perform some tasks after the Spring Context is initialized (Beans are also initialized at this stage).
For my problem statement, from the description of Spring Docs ApplicationEnvironmentPreparedEvent looked promising, but the hook did not work.
#SpringBootApplication
public class App {
public static void main(String[] args) throws IOException {
SpringApplication.run(App.class, args);
}
#EventListener
public void onStartUp(ContextRefreshedEvent event) {
System.out.println("ContextRefreshedEvent"); // WORKS
}
#EventListener
public void onShutDown(ContextClosedEvent event) {
System.out.println("ContextClosedEvent"); // WORKS
}
#EventListener
public void onEvent6(ApplicationStartedEvent event) {
System.out.println("ApplicationStartedEvent"); // WORKS BUT AFTER ContextRefreshedEvent
}
#EventListener
public void onEvent3(ApplicationReadyEvent event) {
System.out.println("ApplicationReadyEvent"); // WORKS WORKS BUT AFTER ContextRefreshedEvent
}
public void onEvent1(ApplicationEnvironmentPreparedEvent event) {
System.out.println("ApplicationEnvironmentPreparedEvent"); // DOESN'T WORK
}
#EventListener
public void onEvent2(ApplicationContextInitializedEvent event) {
System.out.println("ApplicationContextInitializedEvent"); // DOESN'T WORK
}
#EventListener
public void onEvent4(ApplicationContextInitializedEvent event) {
System.out.println("ApplicationContextInitializedEvent");
}
#EventListener
public void onEvent5(ContextStartedEvent event) {
System.out.println("ContextStartedEvent");
}
}
Update
As suggested by M.Deinum in the comments, I tried adding an application context initializer like below. It doesn't seem to be working either.
public static void main(String[] args) {
new SpringApplicationBuilder()
.sources(App.class)
.initializers(applicationContext -> {
System.out.println("INSIDE CUSTOM APPLICATION INITIALIZER");
})
.run(args);
}
Update #2
While my problem statement is regarding loading properties, my question/curiosity is really about how to run some code before the classes are initialized as beans and put into Spring IoC container. Now, these beans require some property values during initialization and I can't/don't want to Autowire them because of the following reason:
As stated in comments and answers, the same can be done using Spring Boot's externalized configuration and profiles. However, I need to maintain application properties and domain-related properties separately. A base domain properties should have at least 100 properties, and the number grows over time. Both application properties and domain-related properties have a property file for different environments (dev, SIT, UAT, Production). Property files override one or more of the base properties. That's 8 property files. Now, the same app needs to be deployed into multiple geographies. That makes it 8 * n property files where n is the number of geographies. I want all the property files stored in a common module so that they can be accessed by different deployables. Environment and geography would be known in run-time as system properties.
While these might be achieved by using Spring profiles and precedence order, I want to have a programmatic control over it (I also would maintain my own property repository). Eg. I would write a convenience utility called MyPropUtil and access them like:
public class MyPropUtil {
private static Map<String, Properties> repository;
public static initialize(..) {
....
}
public static String getDomainProperty(String key) {
return repository.get("domain").getProperty(key);
}
public static String getAppProperty(String key) {
return repository.get("app").getProperty(key);
}
public static String getAndAddBasePathToAppPropertyValue(String key) {
...
}
}
#Configuration
public class MyComponent {
#Bean
public SomeClass getSomeClassBean() {
SomeClass obj = new SomeClass();
obj.someProp1(MyPropUtil.getDomainProperty('domainkey1'));
obj.someProp2(MyPropUtil.getAppProperty('appkey1'));
// For some properties
obj.someProp2(MyPropUtil.getAndAddBasePathToAppPropertyValue('some.relative.path.value'));
....
return obj;
}
}
From the docs, it seems like ApplicationEvents and ApplicationInitializers fit my need, but I am not able to get them to work for my problem statement.
Bit late to the party but hopefully I can offer a solution to your updated problem statement.
This will focus on problem of how to run some code before the classes are initialized as beans and put into Spring IoC container
One issue I notice is that you're defining your application events via the #EventListener annotation.
These are only called once all beans are initiated since these annotations are processed by EventListenerMethodProcessor which is only triggered when the context is ready (see SmartInitializingSingleton#afterSingletonsInstantiated)
As such, some of the events that occur before the context is ready. e.g. ContextStartedEvent, ApplicationContextInitializedEvent won't make it to your listener.
Instead, what you can do is extend the interface for these events directly.
#Slf4j
public class AllEvent implements ApplicationListener<ApplicationEvent> {
#Override
public void onApplicationEvent(final ApplicationEvent event) {
log.info("I am a {}", event.getClass().getSimpleName());
}
Note the missing #Component. Even bean instantiation can occur after some of these events. If you use #Component, then you'll get the following logs
I am a DataSourceSchemaCreatedEvent
I am a ContextRefreshedEvent
I am a ServletWebServerInitializedEvent
I am a ApplicationStartedEvent
I am a ApplicationReadyEvent
Still better and more instant than the annotative listeners but will still not receive the initialization events. For that, what you need to do is follow the instructions found here
To summarize,
Create directory resources/META-INF
Create file spring.factories
org.springframework.context.ApplicationListener=full.path.to.my.class.AllEvent
The result:-
I am a ApplicationContextInitializedEvent
I am a ApplicationPreparedEvent
I am a DataSourceSchemaCreatedEvent
I am a ContextRefreshedEvent
I am a ServletWebServerInitializedEvent
I am a ApplicationStartedEvent
I am a ApplicationReadyEvent
In particular, ApplicationContextInitializedEvent should allow you to perform whatever per-instantiation tasks you need.
I think Spring Cloud Config is a perfect solution for your problem statement. Detailed documentation Here
Spring Cloud Config provides server-side and client-side support for externalized configuration in a distributed system.
So you can easily manage the configurations outside of the app, as well as all the instances will use same configurations.
Create a bean that will be a properties repository and inject it in other beans requiring properties.
In your example, instead of having static methods in MyPropUtil, make the class a bean itself with instance methods. Initialize Map<String, Properties> repository in the initialize method annotated with #PostConstruct.
#Component
public class MyPropUtil {
private static final String DOMAIN_KEY = "domain";
private static final String APP_KEY = "app";
private Map<String, Properties> repository;
#PostConstruct
public void init() {
Properties domainProps = new Properties();
//domainProps.load();
repository.put(DOMAIN_KEY, domainProps);
Properties appProps = new Properties();
//appProps.load();
repository.put(APP_KEY, appProps);
}
public String getDomainProperty(String key) {
return repository.get(DOMAIN_KEY).getProperty(key);
}
public String getAppProperty(String key) {
return repository.get(APP_KEY).getProperty(key);
}
public String getAndAddBasePathToAppPropertyValue(String key) {
//...
}
}
and
#Configuration
public class MyComponent {
#Autowired
private MyPropUtil myPropUtil;
#Bean
public SomeClass getSomeClassBean() {
SomeClass obj = new SomeClass();
obj.someProp1(myPropUtil.getDomainProperty("domainkey1"));
obj.someProp2(myPropUtil.getAppProperty("appkey1"));
// For some properties
obj.someProp2(myPropUtil.getAndAddBasePathToAppPropertyValue("some.relative.path.value"));
//...
return obj;
}
}
Or you can inject MyPropUtil directly to the SomeClass:
#Component
public class SomeClass {
private final String someProp1;
private final String someProp2;
#Autowired
public SomeClass(MyPropUtil myPropUtil) {
this.someProp1 = myPropUtil.getDomainProperty("domainkey1");
this.someProp2 = myPropUtil.getAppProperty("appkey1");
}
//...
}
I feel like your main issue is that you need to maintain application properties and domain-related properties separately.
From spring's perspective, it doesn't really matter since all properties files are kinda merged together after they have been loaded in memory.
So for example, you have two files that contain some properties:
application.related=property1 # this is in application.properties
domain.related=property2 # this is in domain-specific.properties
After they have been loaded, you will get one big thing that contains all properties, if I am not mistaken, it is a org.springframework.core.env.ConfigurableEnvironment instance.
Then what you need to do is just inject the property you need using something like #Value.
For the main issue, to separate properties into different files, you just need to specify spring's spring.config.name property (via environment variable, command line or programmatically). Following the above example, it should be spring.config.name=application,domain-specific.
Furthermore, if you really want to have programmatic control, you can add a custom EnvironmentPostProcessor which exposes the ConfigurableEnvironment instance.
As explaned in this post you can add external property files like this;
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer();
properties.setLocation(new FileSystemResource("/Users/home/conf.properties"));
properties.setIgnoreResourceNotFound(false);
return properties;
}
If you don't want to use this, just read the property file with jackson and set the properties to System.setProperty("key","value") in the main method before spring starts.
If you don't want to use this too, take a look at the BeanPostProcessor#postProcessBeforeInitialization method. It runs before bean properties initialized by spring.
I might be missing what exactly do you mean by "Beans initialization", probably an example of such a bean in a question could be beneficial.
I think you should differentiate between properties reading part and bean initialization.
By the time of bean initialization, properties are already read and available. Thats a part of spring magic, if you wish.
That's why the following code works for example:
#Component
public class MySampleBean {
public MySampleBean(#Value("${some.prop}" String someProp) {...}
}
It doesn't matter from where do these property come (spring boot defines many different ways of these places with precedence between them), it will happen before the initialization of beans happens.
Now, lets get back to your original question:
I want to load properties from a properties file in a classpath or at external location (before the beans are initialized - irrelevant).
In spring / spring-boot there is a concept of profiles that basically allows to create a file application-foo.properties (or yaml) and when you load with --spring.profiles.active=foo it will automatically load properties defined in this application-foo.properties in addition to the regular application.properties
So you can place the stuff that you want to "load from classpath" into application-local.properties (the word local is for the sake of example only) and start the application with --spring.profiles.active=local (in the deployment script, docker file or whatever)
If you want to run the property from external location (outside the classpath) you can use: --spring.config.location=<Full-path-file>
Note that even if you put some properties into a regular application.properties and still use --spring.config.location with the same key-value pairs they will take precedence over the properties in the classpath.
Alternatively you can use only --sring.profiles.active=local or remote and do not use config locations at all.
You can configure external location directly in the command line:
java -jar app.jar --spring.config.location=file:///Users/home/config/external.properties
You can use WebApplicationInitializer to execute code before classes are initialized as beans
public class MyWebInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
var ctx = new AnnotationConfigWebApplicationContext();
ctx.register(WebConfig.class);
ctx.setServletContext(servletContext);
We create an AnnotationConfigWebApplicationContext and register a web configuration file with register().
You can check if PropertySource may help you.
Example:
#PropertySource({"classpath:persistence/persistence.properties"})
You can use this annotation on every #Configuration or #SpringBootApplication bean
It sounds like you want to take some ownership of a part of the bean initialization. Typically people think of Spring completing the bean configuration, but in your case it might be easier to consider Spring as starting it.
So, your bean has some properties you want to configure, and some that you want Spring to configure. Just annotate the ones you want Spring to configure (with #Autowire or #Inject, or whatever flavour you prefer), and then take over the control from there, using #PostConstruct or InitializingBean.
class MyMultiStageBoosterRocket {
private Foo foo;
private Bar bar;
private Cat cat;
#Autowire
public MyMultiStageBoosterRocket(Foo foo, Bar bar) {
this.foo = foo;
this.bar = bar'
}
// called *after* Spring has done its injection, but *before* the bean
// is registered in the context
#PostConstruct
public void postConstruct() {
// your magic property injection from whatever source you happen to want
ServiceLoader<CatProvider> loader = ServiceLoader.load(CatProvider.class);
// etc...
}
}
Of course your mechanism for property resolution would need to be available statically somehow, but that seems to fit with you MyPropUtil example.
Getting far more involved, you start looking at Bean Post Processors directly (#PostConstruct is a simple variant of sorts).
There's a previous question, with a useful answer, here How exactly does the Spring BeanPostProcessor work?, but for simplicity, you'd do something like
public class CustomBeanPostProcessor implements BeanPostProcessor {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
// fixme: detect if this bean needs fancy initialization
return bean;
}
}
Clearly #PostProcess, or InitializingBean are simpler, but the custom post processor has a big advantage... it can be injected with other Spring managed beans. That means you can Spring manage your property injection whatever-thing, and still manually manage the actual injection process.
Just try to load everything you need in main before
SpringApplication.run()
call
public static void main(String[] args) {
// before spring initialization
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
SpringApplication.run(CyberRiskApplication.class, args);
}
You can use ApplicationEnvironmentPreparedEvent but it can't be configured using EventListener annotation. Because by this time Bean drfinitions are not loaded. See the below link on how to cofigure this event.
https://www.thetechnojournals.com/2019/10/spring-boot-application-events.html

How to avoid the use of Spring annotations in my java beans and use them only in the configuration class?

I'm new in Spring and this is my first post here, I'm starting to use spring annotations, I was able to cofigure my project using XML configuration and now I'm able to configure it using only annotations and avoiding XML.
But my current need is to avoid the use of annotations in my java classes (beans) and use it only in my AppConfig.java class which I use to configure Spring.
This is my current working configuration:
AppConfig.java
#Configuration
#ComponentScan(basePackageClasses= {BlocBuilder.class,... all my classes go here})
public class AppConfig {
#Bean
#Scope("prototype")
public BlocBuilder blocBuilder(){
return new BlocBuilder();
}
}
And this is one of my java classes.
BlocBuilder.java
public class BlocBuilder {
#Autowired
#Qualifier("acServices")
private SomeInterface someInterface;
public SomeInterface getSomeInterface() {
return someInterface;
}
public void setSomeInterface(SomeInterface someInterface) {
this.someInterface = someInterface;
}
What I want to achieve is to avoid the use of annotations in my classes for example in my BlocBuilder.java class I don't want to have annotations and move them to my config class.
How can I manage it?
Any help whould be really appreciated.
Constructor injection is what you're looking for. Create a 1-arg constructor in BlocBuilder which takes SomeInterface type argument. And then in config class, pass it as argument:
#Configuration
#ComponentScan(basePackageClasses= {BlocBuilder.class,... all my classes go here})
public class AppConfig {
#Bean
public SomeInterface someInterface() {
return new SomeInterfaceImpl();
}
#Bean
#Scope("prototype")
public BlocBuilder blocBuilder(){
return new BlocBuilder(someInterface());
}
}
I wouldn't recommend a config class. It'll couple all your beans together.
Spring configuration doesn't need to be an all or nothing thing: annotations or XML. You can mix and match as you choose. Put annotations in the classes you want and use XML for the rest.

Spring autowire using annotations and a type defined in a properties file?

My goal is a framework where concrete types of beans can be easily changed by a properties file. I also prefer annotations to XML. Ideally I'd to use a combination of #Resource and SpEL like this:
#Resource(type="#{myProperties['enabled.subtype']}")
SomeInterface foo;
where I've loaded myProperties with a PropertiesFactoryBean or <util:properties> from a file that includes:
enabled.type = com.mycompany.SomeClassA; // which implements SomeInterface
This doesn't work because the argument of type must be a literal, i.e., no SpEL allowed. What's the best practice here?
Update: See my answer below.
This is exactly the use case for Spring Java Configuration.
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java
Or you can alternatively make a Factory.
Using: org.springframework.beans.factory.FactoryBean<SomeInterface>
The name of the bean that implements FactoryBean will be seen as a "SomeInterface" even though its not.
I think it is not possible, the solution I tend to adopt is to use a factory that creates the different objects depending on a configuration property (enabled.type in your example).
A second alternative could be to use injection by name:
#Resource(name="beanName")
And last, if you use Spring 3.1+ you can try to use profiles, and have different bean sets in different profiles, if that solves your problem.
Spring's Java Configuration and Bean Definition Profiles turn out to be exactly what I was looking for (thanks #Adam-Gent and #Guido-Garcia). The former seems necessary for the dynamic element, and the latter promotes a better practice.
Here's a solution with Java config and properties:
#Configuration
public class SomeClassConfig {
#Value("#{myProperties['enabled.subtype']}")
public Class enabledClass;
#Bean SomeInterface someBean()
throws InstantiationException, IllegalAccessException {
return (SomeInterface) enabledClass.newInstance();
}
}
Here's a slightly less dynamic solution with profiles.
#Configuration
#Profile("dev")
public class DevelopmentConfig {
#Bean SomeInterface someBean() {
return new DevSubtype();
}
}
#Configuration
#Profile("prod")
public class ProductionConfig {
#Bean SomeInterface someBean() {
return new ProdSubtype();
}
}
With profiles, the active profile(s) are declared using one of a variety of methods such as via system property, JVM property, web.xml, etc. For example, with a JVM property:
-Dspring.profiles.active="dev"

How to inject dependencies into a self-instantiated object in Spring?

Let's say we have a class:
public class MyClass {
#Autowired private AnotherBean anotherBean;
}
Then we created an object of this class (or some other framework have created the instance of this class).
MyClass obj = new MyClass();
Is it possible to still inject the dependencies? Something like:
applicationContext.injectDependencies(obj);
(I think Google Guice has something like this)
You can do this using the autowireBean() method of AutowireCapableBeanFactory. You pass it an arbitrary object, and Spring will treat it like something it created itself, and will apply the various autowiring bits and pieces.
To get hold of the AutowireCapableBeanFactory, just autowire that:
private #Autowired AutowireCapableBeanFactory beanFactory;
public void doStuff() {
MyBean obj = new MyBean();
beanFactory.autowireBean(obj);
// obj will now have its dependencies autowired.
}
You can also mark your MyClass with #Configurable annotation:
#Configurable
public class MyClass {
#Autowired private AnotherClass instance
}
Then at creation time it will automatically inject its dependencies. You also should have <context:spring-configured/> in your application context xml.
Just got the same need and in my case it was already the logic inside non Spring manageable java class which had access to ApplicationContext. Inspired by scaffman.
Solved by:
AutowireCapableBeanFactory factory = applicationContext.getAutowireCapableBeanFactory();
factory.autowireBean(manuallyCreatedInstance);
I used a different approach. I had spring loaded beans that I wanted to call from my extended classes of a third-party library that created its own threads.
I used approach I found here https://confluence.jaytaala.com/display/TKB/Super+simple+approach+to+accessing+Spring+beans+from+non-Spring+managed+classes+and+POJOs
In the non-managed class:
{
[...]
SomeBean bc = (SomeBean) SpringContext.getBean(SomeBean.class);
[...]
bc.someMethod(...)
}
And then as a helper class in the main application:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
#Component
public class SpringContext implements ApplicationContextAware
{
private static ApplicationContext context;
public static <T extends Object> T getBean(Class<T> beanClass)
{
return context.getBean(beanClass);
}
#Override
public void setApplicationContext(ApplicationContext context) throws BeansException
{
SpringContext.context = context;
}
}
I wanted to share my solution that follows the #Configurable approach as briefly mentioned in #glaz666 answer because
The answer by #skaffman is nearly 10 years old, and that does not mean not good enough or does not work
The answer by #glaz666 is brief and didn't really help me solve my problem but, did point me in the right direction
My setup
Spring Boot 2.0.3 with Spring Neo4j & Aop starts (which is irrelevant anyway)
Instantiate a bean when Spring Boot is ready using #Configurable approach (using ApplicationRunner)
Gradle & Eclipse
Steps
I needed to follow the steps below in order to get it working
The #Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = false) to be placed on top of your Bean that is to be manually instantiated. In my case the Bean that is to be manually instantiated have #Autowired services hence, the props to above annotation.
Annotate the Spring Boot's main XXXApplicaiton.java (or the file that is annotated with #SpringBootApplication) with the #EnableSpringConfigured and #EnableLoadTimeWeaving(aspectjWeaving=AspectJWeaving.ENABLED)
Add the dependencies in your build file (i.e. build.gradle or pom.xml depending on which one you use) compile('org.springframework.boot:spring-boot-starter-aop') and compile('org.springframework:spring-aspects:5.0.7.RELEASE')
New+up your Bean that is annotated with #Configurable anywhere and its dependencies should be autowired.
*In regards to point #3 above, I am aware that the org.springframework.boot:spring-boot-starter-aop transitively pulls the spring-aop (as shown here mavencentral) but, in my case the Eclipse failed to resolve the #EnableSpringConfigured annotations hence, why I explicitly added the spring-aop dependency in addition to the starter. Should you face the same issue, just declare the dependency or go on adventure of figuring out
Is there a version conflict
Why the org.springframework.context.annotation.aspect.* is not available
Is your IDE setup properly
Etc etc.
This worked for me:
#Configuration
public class AppConfig {
#Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
See more information: https://docs.spring.io/spring-javaconfig/docs/1.0.0.m3/reference/html/creating-bean-definitions.html
Found the following way useful for my use case. Sharing here for reference, credit goes to the blogger entirely. This creates a static field and populates that from Spring and then provides a public static method which returns the field populated above.
https://sultanov.dev/blog/access-spring-beans-from-unmanaged-objects/

Categories

Resources