If I specify what should be injected into a property, like
<property name="xxx" ref="some_bean" />
or
<property name="xxx">
<bean .../>
</property>
then I have to write a setter method.
May I use some annotation to avoid this like #autowired?
You can do this with constructor injection. 3 main ways to do this:
XML:
<bean id="beanA" class="com.BeanA">
<constructor-arg ref="beanB"/>
</bean>
<bean id="beanB" class="com.BeanB"/>
JavaConfig:
#Configuration
public class MyConfig {
#Bean
public BeanA beanA() {
return new BeanA(beanB());
}
#Bean
public BeanB beanB() {
return new BeanB();
}
}
Autowiring:
#Component
public class BeanA {
private final BeanB beanb;
// This assumes that there is a BeanB in your application context already
#Autowired
public BeanA(final BeanB beanB) {
this.beanB = beanB;
}
}
You can take Autowiring even further, and wire directly to the field:
#Component
public class BeanA {
// This assumes that there is a BeanB in your application context already
#Autowired
private final BeanB beanb;
}
Related
I have a Spring Java Configuration class that defines a bean inside, e.g.:
#Configuration
public class SomeConfig{
private String someProperty;
public SomeConfig(String someProperty){
this.someProperty=someProperty;
}
#Bean
public SomeBean someBean(){
SomeBean s = new SomeBean(someProperty);
return s;
}
}
I need to have several instances of SomeBean, each of them configured with a different someProperty value.
In a Spring Boot application is it possible to #Import the same class multiple times?
SELF-ANSWERED: If you import the same #Configuration class, it will override the existing one.
How can something like this be done with Spring Java Config?
UPDATE:
In XML I can do:
<bean class="x.y.z.SomeBean">
<constructor-arg value="1"/>
</bean>
<bean class="x.y.z.SomeBean">
<constructor-arg value="2"/>
</bean>
I am looking for an equivalent with Java Config
I just had to use another #Configuration class that defined as many SomeConfig beans as needed:
#Configuration
public class ApplicationConfig{
#Bean
public SomeConfig someConfig1(){
return new SomeConfig("1");
}
#Bean
public SomeConfig someConfig2(){
return new SomeConfig("2");
}
}
#Configuration
public class SomeConfig{
private String someProperty;
#Bean
public OtherBean otherBeanOne(){
OtherBean otherBean = new OhterBean();
otherBean.setSomeBean(someBean("property1"));
return otherBean;
}
#Bean
public OtherBean otherBeanTwo(){
OtherBean otherBean = new OhterBean();
otherBean.setSomeBean(someBean("property2"));
return otherBean;
}
#Bean
public SomeBean someBean(String someProperty){
SomeBean s = new SomeBean(someProperty);
return s;
}
}
I have a list of services that extend an AbstractService class. The AbstractService holds the DAO (you can call it "repository") and has the getter/setter for the DAO:
/**
* #param <T> Entity type
* #param <K> Entity ID type
* #param <S> DAO type
*/
public abstract class AbstractService<T, K extends Serializable, S extends BaseDAO<T, K>> implements BaseService<T, K> {
private S dao;
public S getDAO() { return dao; }
public void setDAO(S dao) { this.dao = dao; }
// Then common methods to all my services, using the DAO, for instance
#Override
public Optional<T> findOne(K key) throws DataException {
return Optional.ofNullable(dao.findOne(key));
}
}
A service example:
#Service
public class EmployeeServiceImpl extends AbstractService<Employee, Integer, EmployeeDAO> implements EmployeeService {
// Some specific methods to that service
}
The related DAO (I use Spring Data JPA):
public interface EmployeeDAO extends BaseDAO<Employee, Integer> {
}
Extending
#NoRepositoryBean
public interface BaseDAO<T, K extends Serializable> extends JpaRepository<T, K> {
}
By the way I added the annotations #Service and #NoRepositoryBean while moving to JavaConfig.
My old XML config was:
<bean id="com.xxx.service._AbstractService" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="com.xxx.dao._TxManager" />
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED,-com.xxx.DataException</prop>
<prop key="update*">PROPAGATION_REQUIRED,-com.xxx.DataException</prop>
<prop key="delete*">PROPAGATION_REQUIRED,-com.xxx.DataException</prop>
</props>
</property>
</bean>
<bean id="com.xxx.service.EmployeeService" parent="com.xxx.service._AbstractBO">
<property name="target">
<bean class="com.xxx.service.EmployeeServiceImpl">
<property name="DAO" ref="com.xxx.dao.EmployeeDAO"/>
</bean>
</property>
</bean>
First question, what is the proper way to inject the generic DAO and handle the service inheritance using JavaConfig?
Second question, how to translate the XML snippet about transactions (com.xxx.service._AbstractBO) to JavaConfig?
Here is what I have so far, 2 classes:
#Configuration
#ComponentScan("com.xxx.service")
public class SpringConfig {
}
And the persistence config
#Configuration
#EnableJpaRepositories("com.xxx.repository")
#EnableTransactionManagement
public class PersistenceConfig {
/* Here so far I defined the DataSource, the EntityManagerFactory,
the PlatformTransactionManager and the JpaVendorAdapter */
}
Thanks in advance for your time!
Here is what I ended up doing: instead of trying to translate my old XML config, I changed the classes design. Since DAOs are required anyway, I inject them in each concrete class constructor which calls a new abstract class constructor I added.
The abstract service:
final private S dao;
public AbstractService(S dao) {
super();
this.dao = dao;
}
// getter protected and setter removed
protected S getDAO() {
return dao;
}
And a concrete service example:
#Service
public class EmployeeServiceImpl extends AbstractService<Employee, Integer, EmployeeDAO> implements EmployeeService {
#Inject
public EmployeeServiceImpl(EmployeeDAO dao) {
super(dao);
}
}
The good thing is I didn't have to change the Java config I posted in my question, meaning #EnableJpaRepositories("com.xxx.repository") and #ComponentScan("com.xxx.service") are sufficient to generate and bind beans.
Below are my classes and xml:
#Component
#Service("ApplicationService")
public class ApplicationServiceImpl implements ApplicationService{
public ApplicationDao getApplicationDao() {
return applicationDao;
}
public void setApplicationDao(ApplicationDao applicationDao) {
this.applicationDao = applicationDao;
}
#Autowired
private ApplicationDao applicationDao;
// some methods..
}
#Service
public interface ApplicationService {
// methods...
}
#Component
#Repository("ApplicationDao")
public class ApplicationDaoImpl implements ApplicationDao {
#Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
// other methods...
}
public interface ApplicationDao {
// methods...
}
xml file:
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven/>
<context:component-scan base-package="com" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- <property name="dataSource" ref="dataSource" /> -->
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
<bean id="ApplicationDao" class="com.dao.impl.ApplicationDaoImpl"/>
<bean id="ApplicationService" class="com.service.impl.ApplicationServiceImpl"/>
Here autowiring is not working.in ApplicationServiceImpl, I am getting applicationDao as null. Have not tested sessionFactory in ApplicationDaoImpl.
I know that if I am using #Component then bean declaration in xmnl is not required.
You should not instantiate service like that..
At the time of application loading, spring container will create all instances defined in spring.xml or annotated classes and it's dependencies..
So you have to access them with the following example code..
ApplicationContext applicationContext = ApplicationContextProvider.getApplicationContext();
ApplicationService applicationService = (ApplicationService) applicationContext.getBean("ApplicationService");
Since ApplicationService is having property that is ApplicationServiceDAOImpl, it's already been created by spring container and will return you..
But in case of directly instantiating manually by you, you are just creating instance of ApplicationService but not for ApplicationServiceDAOImpl.. so it obviously returns null
I'm currently using this approach only to access beans or services..
update for comment
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
#Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
applicationContext = arg0;
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
}
Hope it helps,
try a change like this:
import org.springframework.beans.factory.annotation.Qualifier;
#Autowired
#Qualifier("ApplicationDao")
private ApplicationDao applicationDao;
this give spring a hint.
If you are using annotations in your application, you should denote it using a tag :
<mvc:annotation-driven />
Add this line in application context xml above component scan tag.
Also, if you are using annotations, remove ApplicationDao and ApplicationService bean declarations from xml.
And don't mark you service and dao classes with both #Component and #Service or #Repository annotations. No need to mark them #Component there. Remove it.
Sorry for my English. I can not to do dependency injection for generic class in spring. Generic class:
abstract class BaseBO<Id, Entity, DAOClass extends DAO<Id, Entity>> implements BO<Id, Entity, DAOClass> {
DAOClass dao;
public DAOClass getDAO() {
return dao;
}
//...
}
Use generic class:
public class TaskBO extends BaseBO<Long, Task, TaskDAO> implements BO<Long, Task, TaskDAO> {
}
I want to do dependency injection in a class TaskBO for property TaskDAO.
But I can only to set dependency TaskDAO via a interface DAO for bean TaskBO:
<bean id="TaskBO" class="com.otv.model.bo.TaskBO">
<property name="DAO" ref="TaskDAO" />
</bean>
<bean id="TaskDAO" class="com.otv.model.dao.TaskDAO">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
How to set dependency injection via class TaskDAO?
Attach stacktrace with error if you have one.
Before all use consistent case for property accessor:
abstract class BaseBO<Id, Entity, DAOClass extends DAO<Id, Entity>> implements BO<Id, Entity, DAOClass> {
DAOClass dao;
public DAOClass getDao() {
return dao;
}
//...
}
Most probably you need a setter for BaseBO.dao property
public void setDao(DAOClass dao) {
this.dao = dao;
}
or
public class TaskBO extends BaseBO<Long, Task, TaskDAO> implements BO<Long, Task, TaskDAO> {
public void setDao(TaskDAO dao) {
super.dao = dao;
}
}
I'm new to Java config. I have a code like this. SomeDao has its own dependency, shouldn't we set the dependencies since we are doing new?
Can someone please help me understand this code?
#Configuration
public class DAOConfiguration {
#Bean(name = "someDao")
public SomeDao someDao() {
return new SomeDao();
}
Are you familiar with how this is done in xml? It is extremely similar to that.
Here is an example of SomeDao being configured with Dep1 (via constructor injection) and Dep2 (via setter injection) in xml:
<bean id="someDao" class="com.example.SomeDao">
<constructor-arg ref="dep1"/>
<property name="dep2" ref="dep2"/>
</bean>
<bean id="dep1" class="com.example.Dep1" />
<bean id="dep2" class="com.example.Dep2" />
This same example in JavaConfig would be configured as such:
#Configuration
public class DAOConfiguration {
#Bean(name = "someDao")
public SomeDao someDao() {
final SomeDao someDao = new SomeDao(dep1());
someDao.setDep2(dep2());
return someDao;
}
#Bean(name="dep1")
public Dep1 dep1() {
return new Dep1();
}
#Bean(name-"dep2")
public Dep2 dep2() {
return new Dep2();
}
}
All three beans are still registered with the ApplicationContext too, so you can have all three of these beans autowired into another class, like so:
#Controller
public class MyController {
#Autowired
private SomeDao someDao;
#Autowired
private Dep1 dep1;
//...some methods
}