How to autowire factorybean instance (not the getObject() object) with annotations? - spring

I know it is possible to get the reference to the factorybean instance when defining the beans with XML (Spring). e.g.:
<property name="factoryBean" ref="&theFactoryBean" />
But is this also posible to do this with annotations? (maybe with #Autowired and #Qualifer?)
Do you have to annotate the factorybean itself to be discovered by Spring component-scan?

Make your bean implement BeanFactoryAware, but as skaffman says, it's not a great practice.

Related

Initialize bean while project deployment spring

I was asked in one of interview that how we can initialize bean while project deployment in Spring ?
There are several options:
Your bean can implement InitializingBean interface and initialization work can be done inside afterPropertiesSet() method
You can just add a method in a bean class and annotate it with #PostConstruct
You can add method in a bean class and mark it as an init method. Using xml config the bean definition would look like this:
<beans>
<bean id="myBean" class="..." init-method="init"/>
</beans>
And using Java config like this:
#Bean(initMethod="init")
public MyBean myBean() {
return new MyBean();
}
You can also implement your own BeanPostProcessor and provide implementation in postProcessAfterInitialization or postProcessBeforeInitialization methods.
One caveat: all this initialization logic is a part of bean lifecycle, which doesn't mean that it will be invoked during the project deployment.
However if bean is a singleton bean then by default it is created during the spring context start up. I guess it is what you mean by project deployment.

Spring inject bean is always singleton

We are using spring 3.2.
We defined a bean myAccountVO in spring.xml files and set the scope to prototype, but the spring creates this bean as singleton bean.
Here is the spring xml:
<bean name="myAccountVO1"
class="valueobject.AccountVO"
scope="prototype" >
<property name="accountNo" value="0105069413007" />
<property name="accountType" value="01" />
</bean>
The service class is:
#Service //I've tested the #Scope("prototype") but no luck
public class AccountSummary {
#Autowired //I also tested #Resource but same result
private AccountSummaryVO myAccountSummaryVO1;
AccountSummaryVO getAccount(){
return myAccountSummaryVO1
}
}
Later we use this service as:
#Autowired
AccountSummary accountSummary;
............
accountSummary.getAccount()
As far as I get the AccountSummary class, itself, is a singleton and will not be instantiated every time.
It seems are very basic usecase, but I don't know what am I missing.
I don't see where you are injecting myAccountVO1.
But I guess when you reveal the injected place that it's probably a member of a bean which itself is not in the scope prototype, e.g. #Service or #Controller. The service bean will be instantiated with a newly created myAccountVO1, but this instance stays there forever.
Change the scope of the containing bean. See 4.5.3 Singleton beans with prototype-bean dependencies.
This applies as well to the beans which have the service beans injected.

"Bean named XXX must be of type[XXX], but was actually of type[XXX]"

when I integrate spring and mybatis, I encountered a error output, saying that:
Bean named 'sqlSessionFactory' must be of type [org.mybatis.spring.SqlSessionFactoryBean], but was actually of type [org.apache.ibatis.session.defaults.DefaultSqlSessionFactory]
here is my code snippet:
ApplicationContext context = new ClassPathXmlApplicationContext("spring_mybatis_integration/spring_config.xml");
SqlSessionFactoryBean sqlSessionFactoryBean = context.getBean("sqlSessionFactory", org.mybatis.spring.SqlSessionFactoryBean.class);
here is my bean definition in xml:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="spring_mybatis_integration/mybatis_config.xml"></property>
<property name="dataSource" ref="dataSource"></property>
</bean>
as you can see, both in java code and in xml file, I associate the bean sqlSessionFactory with class org.mybatis.spring.SqlSessionFactoryBean, why does the error output tell me another non-relative class name org.apache.ibatis.session.defaults.DefaultSqlSessionFactory?
Thanks a lot!
Version Info:
mybatis 3.1.1
spring 3.2.0
mybatis-spring 1.1.1
There is no point to accessSqlSessionFactoryBean via dependency injection, normally we work with the objects created by the Factory Beans, not the Factory Beans themselves, in this case the Factory Bean returns a DefaultSqlSessionFactory instance.
See Customizing instantiation logic with the FactoryBean Interface
But if you really want to access the FactoryBean instance, you should use ampersand symbol & see Spring: Getting FactoryBean object instead of FactoryBean.getObject()
Yes, the concept of the Factory Beans that return factories may be a bit confusing, but that is how things work in Spring.
So it's likely SqlSessionFactory instead of the SqlSessionFactoryFactoryBean is what you want.
update: actually MyBatis even explained this in the documentation on SqlSessionFactoryBean
Note that SqlSessionFactoryBean implements Spring's FactoryBean
interface (see section 3.8 of the Spring documentation). This means
that the bean Spring ultimately creates is not the
SqlSessionFactoryBean itself, but what the factory returns as a result
of the getObject() call on the factory. In this case, Spring will
build an SqlSessionFactory for you at application startup and store it
with the name sqlSessionFactory

Autowiring spring bean by name using annotation

In Springs latest version, we can autowire a bean using annotation as #Autowired. This will autowire the bean using its type(or constructor, if applied on it).
Is there any way I can use the #Autowired annotation based on the bean name which we were doing without annotation in Spring's XML file as autowire="byName"?
You can use:
#Autowired
#Qualifier("beanname")
According to the #Qualifier javadoc
This annotation may be used on a field or parameter as a qualifier for candidate beans when autowiring
You can use JSR-250 #Resource for by-name bean autowiring, unless you need constructor injection or multi-parameter method injection.
From the docs:
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.
If you want to define name of the bean with which they will be registered in DI container, you can pass the name in annotation itself e.g. #Service (“employeeManager”).
Then using below code you can enable autowire by Name
#Autowired
#Qualifier("employeeManager")
private EmployeeManagerService employeeManagerService;
I was using bean name proxy which was messing up autowiring by name. #Resource didn't have that issue since it doesn't care about type. So now I know one reason for this recommendation by Spring developers :-) Just FYI
Use #Component("beanname") in the java class definition of your bean
Then while autowiring use JSR 330
#Inject
#Named(Value="beanname")

Spring Standard Bean Injection vs. Autowiring

As far as I understand When Using Dependency Injection all bean are initializing on Start.
<bean id="userPreferences" class="com.foo.UserPreferences">
</bean>
<!-- a singleton-scoped bean injected to the above bean -->
<bean id="userService" class="com.foo.SimpleUserService">
<!-- a reference to the userPreferences bean -->
<property name="userPreferences" ref="userPreferences"/>
</bean>
and the configuration above means that userService and userPreferences created when application starts. Is it correct?
When using Autowiring and using <context:component-scan>
public class SimpleUserService{
#Autowired
UserPreferences userPreferences;
//omitted
}
1) Is userPreference created on Application init?
2) What is the default scope for bean injected by autowire and how can we change it?
3) How affects bean creation and bean injection?
Hope I made myself clear.
First of all you should add #Service or #Component to the SimpleUserService class.
1 Yes, the ONE instance of UserPreferences is created at application intialization
2 Default scope is singleton, You can change it with the #Scope annotation (#See Spring Reference: 3.11.4.4 Specifying bean scope)
3 Component scan and XML configuration work in the same way (life cycle)
Maybe you should spend some time in understanding the Spring life cycle. You need to understand that Spring works a bit in this way (not 100% correct):
first it creates a pool of beans
then it injects the properties into the beans
But it does NOT work this way: taking a class, look what references it needs creating this references (recursive) and then creating the class.
If you understand this, then you will also understand, that the #Scope of a bean is defined at the bean declaration/class, but not at the references.
1) Is userPreference created on
Application init?
In either case userPreferences is initialized when Spring Context is loaded. You can change this behavior by adding lazy-init="true" to the bean configuration.
2) What is the default scope for bean
injected by autowire and how can we
change it?
The scope of what is injected is all beans loaded into Spring. If you import an XML configuration from another project, it too would be included. I'm not sure if you can limit your scope.
3) How affects bean creation and bean
injection?
Whether is autowired, or configured via XML, the behavior should be the same. I prefer explicitly defining dependencies over automatic annotations. Then again I also like strongly typed languages.
the configuration above means that userService and userPreferences created when application starts. Is it correct?
Yes
Is userPreference created on Application init?
Yes
What is the default scope for bean injected by autowire and how can we change it?
The default scope is always "singleton". This can be changed either using #Scope with #Bean or the scope XML attribute on <bean>.
How affects bean creation and bean injection?
This isn't a clear question. If you change the bean scope, you change when it gets created (start of application, on each request, on each session, etc). The wiring configuration remains the same, only the lifecycle changes.
The #autowired notation is an obsolete way to say #inject. THe latter is a feature of JavaEE 6.
stackoverflow.com/questions/7142622/what-is-the-difference-between-inject-and-autowired-in-spring-framework-which

Resources