Can I use #Autowired variable in #Bean method? - java

Is this valid or bar is null when getFoo is invoked?
#Configuration
class Config
{
#Bean
Foo getFoo()
{
return new Foo(bar);
}
#Autowired
Bar bar;
}

Yes you can do that, all Autowired is doing is injecting Bar. Its not good way but you can do that.

This depends on a few things: the type of the #Bean, the moment in the lifecycle of the beans involved that one of them is required, the context in which the #Autowired target bean is declared.
If you're not trying to do anything fancy, then, yes, it will work.

Related

Spring dependency injection via setter method and Configuration class

I wanna switch from xml based spring configuration into java-based. For constructor type injection it is easy. Example I am using:
#Configuration
public class BeanConfiguration {
#Bean
public GreetingService greetingService(GreetingDao greetingDao) {
return new GreetingService(greetingDao);
}
#Bean
public GreetingDao greetingDao() {
return new GreetingDao();
}
}
However, when I want to inject through setter method I am doing something like this:
#Configuration
public class BeanConfiguration {
#Bean
public MeetingDao meetingDao() {
return new MeetingDao();
}
#Bean
public MeetingService meetingService(MeetingDao meetingDao) {
MeetingService meetingService = new MeetingService();
meetingService.setMeetingDao(meetingDao);
return meetingService;
}
}
I am not sure if this is a possible way to inject with Java-based Configuration and setter method. Unfortunately I cannot find any example (for constructor dependencies a lot of examples exists). Also I am not sure in case of Java-based configuration when should I use constructor and when setter. In Spring docs it is described that I should use constructor for required and setter for optional dependency. However, I see it as the same result for this kind of approach.
Thanks for any clarification.
Adam
Under the assumption that you cannot change the classes themselves, you could always just not return the bean until you have injected all the values.
#Configuration
public class YourConfig{
#Value("${some.value.from.properties}")
private String someValue;
#Bean
#Autowired
public YourBean yourBean(TheDependency theDependency){
YourBean bean = new YourBean();
bean.setTheDependency(theDependency);
bean.setSomeValue(someValue);
return bean;
}
}
Constructor injection is always preferred with class dependencies, but not always possible.
If you have access to changing the source for these services and beans you are creating, then I suggest using constructor injection and placing "#Service" on the class and "#Autowired" on the constructors.
Properties are an example of "optional" dependencies; it is common to default values and behavior if not provided. I prefer just placing the "#Value" directly on that field instead of my constructor because otherwise you might end up with WAY too many parameters. This is "setter" injection, but you don't want an actual setter method (again, not normally anyways); you only want Spring to change the value, not any of your other code.
Using "#Value" is fine if you only have one or two properties(or 3? It's not an exact science); however, if you find you have a lot of fields with "#Value" then you should use a configuration bean instead. An "#ConfigurationProperties" bean can also be treated the same way with "setter" injection, but I prefer constructor injection to be sure that at least the bean is never null, even though it's values might be.

Spring bean lazy initialization

I was thinking about the lazy-initialization of beans in Spring. For me, it wasn't crystal clear that the "lazy" here means that a bean will be created when it's referenced.
I expected that the lazy initialization support in Spring is different. I thought this is a "method-call" based lazy creation. What I mean by this is, whenever any method is being called on the method, it will be created.
I think this could be easily solved by creating a proxy instance of the specific bean and do the initialization on any method call.
Am I missing something why this is not implemented? Is there any problem with this concept?
Any feedback/idea/answer will be appreciated.
You can achieve the behavior you want by scoping your bean with a proxyMode of ScopedProxyMode.TARGET_CLASS (CGLIB) or ScopedProxyMode.INTERFACES (JDK).
For example
public class StackOverflow {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Conf.class);
Bar bar = ctx.getBean(Bar.class);
System.out.println(bar);
System.out.println(bar.foo.toString());
}
}
#Configuration
class Conf {
#Bean
#Lazy
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public Foo foo() {
System.out.println("heyy");
return new Foo();
}
#Bean
public Bar bar() {
return new Bar();
}
}
class Bar {
#Autowired
public Foo foo;
}
class Foo {
}
will print
com.example.Bar#3a52dba3
heyy
com.example.Foo#7bedc48a
demonstrating that the Foo bean was initialized through its #Bean factory method only after a method was invoked on the Foo instance injected by the Spring context in the Bar bean.
The #Scope annotation can be used in a class declaration as well.
bellow is my views:
Bean types in Spring Container:
There are two Scope bean type in Spring Container.One is Prototype, this type bean won't exist lazy-init concept, because these beans will be instantiated when clients invoke the getBean() method every time. Another is Singleton, these bean will be instantiated once, these beans can be lazily instantiated(just be instantiated when they're used, such as #Autowired, refrenced) if you define the bean use #Lazy or lazy-init=true.
How to implement lazy-init:
Yes, common implementation is Proxy Mode. Spring use JDK Dynamic Proxy and Cglib to implement Proxy, you can go further understanding about these techs.
Hope to help you.

Does calling #Bean methods create a new instance of the object or the bean instance?

In the code below, is calling bar() inside foo.setBar(bar()) and blah.setBar(bar()) using two difference instances of Bar? Or is it using a bean instance of Bar instead? If it's a bean instance, how does Spring do it automagically? Is it achieved by proxy?
#Configuration
public class AppConfig {
#Bean
public Foo foo() {
Foo foo = new Foo();
foo.setBar(bar());
return foo;
}
#Bean
public Bar bar() {
return new Bar();
}
#Bean
public Blah blah() {
Blah blah = new Blah();
blah.setBar(bar());
return blah;
}
}
Spring creates a proxy of your #Configuration annotated classes. This proxy intercepts #Bean method calls and caches the bean instances so that further calls to the same #Bean method refers to the same bean instance.
Hence in your case both calls to bar() method refers to the same Bar instance.The Bar instance is actually a singleton per application context.This is why the #Bean methods visibility is restricted to either protected , package or public because Spring needs to override your #Bean methods in the proxy.
Single bean instance will be used and it is achieved using proxies. Spring uses the concept of Inheritance based proxies to achieve this. Please take a look at - How to exactly work the Spring Inheritance-based Proxies configuration?
the same bean instance will be used in your case because a singleton scope is used by default for '#Bean' annotation.
yes, it's achived by spring proxying internals.

Create a bean and autowire it

I currently have numerous classes with a field like
private MyStuff myStuff = new MyStuff();
It would be preferable if there was a MyStuff singleton which all the classes used. Our project has a MyConfiguration class with some Beans in it, but they don't seem to get used, at least not directly, so I can't use them for examples. I have been tasked to create a MyStuff bean in the MyConfiguration class, and then inject it into my other classes.
What I have so far:
#Configuration
public class MyConfiguration
{
#Bean
public MyStuff myStuff()
{
return new MyStuff();
}
}
public SomeClass
{
public void dealWithStuff()
{
someStuff.myMethod();
}
#Autowired
private MyStuff someStuff;
}
This compiles but does not run. someStuff is null when it tries to call myMethod(). Apparently it does not see the bean or make the connection. What am I missing?
I'm going to make an assumption, so correct me if I'm wrong: you are creating instances of SomeClass yourself. Something like
SomeClass someInstance = new SomeClass();
outside of any Spring component.
In this case, how do you expect Spring to inject anything since it's not even process it.
You need to let Spring create objects (beans) that need to have other beans injected.
The problem is naming. Refer to this for a complete description but briefly it says
If you intend to express annotation-driven injection by name, do not primarily use #Autowired, even if is technically capable of referring to a bean name through #Qualifier values. Instead, use the JSR-250 #Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.
It means that you should be doing something like this:
#Resource(name="myStuff")
public void setSomeStuff(MyStuff someStuff){
this.someStuff = someStuff;
}
The reason is that you have defined your bean as myStuff but referring it as someStuff.
Also to have a singleton instance, all you need is to define its scope as singleton in your Spring Configuration as following:
#Configuration
public class MyConfiguration
{
#Bean #Scope(BeanDefinition.SCOPE_SINGLETON)
public MyStuff myStuff()
{
return new MyStuff();
}
}
As I see in your code, your object reference name is "someStuff" but you are referring to myStuff you should use someStuff.myMethod();

Spring DI: Specify default component for FactoryBean<T>

I have two implementations of interface IFoo: Foo1 and Foo2.
I need the context to be able to inject the correct one for any class that wants an IFoo without that class knowing what implementation it's going to get (so no use of #Qualifier).
Example of usage:
class Bar {
#Autowired IFoo foo;
}
I have a FactoryBean<IFoo> class that has the logic for which one to return.
The issue is that I also want to have those two impls go through the IOC because they have dependencies themselves.
public class FooFactory implements FactoryBean<Foo> {
#Autowired Foo1 foo1;
#Autowired Foo2 foo2;
#Override
public IFoo getObject() throws Exception {
if(someLogic()){
return foo1;
}
return foo2;
}
}
If I autowire them into the factory I get an exception of
"No unique bean of type IFoo is defined: expected single matching bean but found 3: [fooFactory, foo1, foo2]"
Any way to tell spring to just use the default of fooFactory for everyone else but use the two implementations inside the factory?
You could use the notion of the "primary" bean. Assuming that you're using XML config, then:
<bean id="fooFactory" class="x.y.FooFactory" primary="true"/>
Now, #Autowired IFoo foo should select the result of the factory, in preference to the foo1 and foo2 beans.
I would also recommend using #Resource inside the factory itself, rather than #Autowired, i.e.
public class FooFactory implements FactoryBean<Foo> {
#Resource Foo1 foo1;
#Resource Foo2 foo2;
This reduces the chance of the autowiring chasing its own tail, since #Resource will inject a specific, named bean (i.e. foo1 and foo2). You'd still use #Autowired in Bar.
If you use #Resource like that, then an alternative to use primary="true" is to exclude the foo1 and foo2 beans from autowiring, e.g.
<bean id="foo1" class="x.y.Foo1" autowire-candidate="false"/>
You can inject a list:
#Resource
private List<IFoo> foos;
Unfortunately it might not work since you are currently constructing FooFactory, so you might get circular dependency error. Try it!
But the more idiomatic wat since Spring 3.1 would be to use #Profile or #Configuration:
#Bean
public IFoo foo() {
if(someCondition) {
return new Foo1(dep1(), dep2());
else
return new Foo1(dep3(), dep4());
}
Where dep...() methods are also #Bean declarations.
You can trz to annotate the factorys result wiht #Primary.
I have not tryed it, and have no IDE here to test it, but may it works.
#Configuration
public class MyFactory {
#Bean
#Primary
public IFoo getFoo () {
...
}
}
Take a look at bean factory scopes.
related post on stackoverflow
Spring Bean scopes

Categories