I have following #Configuration class
#Configuration
public class SomeClass {
#Bean
public BeanClass get() {
return new BeanClass()
}
}
Now I want to autowire BeanClass in some other class
public class SomeClass2 {
#Autowired
BeanClass beanCLass
}
Currently beanClass is coming null.
What and how exactly I need to tell spring for this autowiring.
According to Spring documentation
By default, the bean name will be that of the method name
get is your bean name, try with this configuration:
#Configurtion
public class SomeClass {
#Bean
public BeanClass beanCLass() {
return new BeanClass()
}
}
Bean
#Component
public class SomeClass2 {
#Autowired
BeanClass beanCLass
}
Your SomeClass2 must be a spring bean. Annotate SomeClass2 with #Component.
Related
I am trying to inject a bean into another bean that uses it. How can I do this?
public class MySpringConfig{
#Bean
public MyObject getMyObject() {
//.....
return MyObjectInstance;
}
#Bean
public SomeObject getSomeObject(MyObject myObject) {
//.....
return SomeObjectInstance;
}
}
I think you can do this with this way, this is working in my project.
#Configuration
public class AppConfig {
#Bean
public Bean1 foo(#Qualifier("bean2") Bean2 bean2) {
return new Bean1(bean2);
}
}
i think that might work!
#Configuration
public class AppConfig {
#Bean
public Bean2 bean2() {
return new Bean2();
}
#Bean
#DependsOn({"bean2"})
public Bean1 foo(#Autowired Bean2 bean2) {
return new Bean1(bean2); // or your can write new Bean1(bean2());
}
}
Parameters don't work exactly in the same way in #Bean and #Component.
For a class annotated with #Component, specifying them is required for the autowired constructor but in a #Bean declaration you don't need to provide a parameter to specify the MyObject dependency to use (while it will work) if that is accessible in the current class, which is your case.
So you want to inject directly the bean by invoking getMyObject() in the #Bean definition.
For example to pass it a constructor arg :
#Bean
public SomeObject getSomeObject() {
//....
// you injected MyObject in the current bean to create
SomeObject object = new SomeObject(getMyObject());
//...
return SomeObjectInstance;
}
And don't forget to annotate the class with #Configuration to make it considered by Spring.
I am trying to solve a problem with the Spring DI. I have two beans (MyFirstBean & MySecondBean) that both implement a given interface (MyBean). Then I have multiple other beans (e.g. OtherBean) that I want to use with either one of the two beans. Autowiring obviously fails for OtherBean since there are multiple instances of MyBean to choose from. Is there any possibility to generically create two instances of each bean
that autowires MyBean and refer to them using qualifiers? I know this is possible by writing a configuration class but since all this is part of an API, I want to keep the overhead as low as possible.
Current Situation:
public interface MyBean {
}
#Component
public class MyFirstBean implements MyBean {
}
#Component
public class MySecondBean implements MyBean {
}
#Component
public class OtherBean {
final MyBean myBean; // error due to multiple beans
public OtherBean(MyBean myBean) {
this.myBean = myBean;
}
}
Desired Situation:
#Component
public class SomeBean {
final OtherBean myBeanUsingFirstBean; // internally autowires MyFirstBean
final OtherBean myBeanUsingSecondBean; // internally autowires MySecondBean
public SomeBean(
#FirstBeanQualifier OtherBean myBeanUsingFirstBean,
#SecondBeanQualifier OtherBean myBeanUsingSecondBean) {
this.myBeanUsingFirstBean = myBeanUsingFirstBean;
this.myBeanUsingSecondBean = myBeanUsingSecondBean;
}
}
Solution 1 :
One of the ways spring autowires beans is by name. If not specified spring will create bean using class name (with small first letter) so for MyFirstBean , bean name will be myFirstBean. Knowing that you can autowire desired bean by changing the name of the property to final MyBean myFirstBean
public interface MyBean {
}
#Component
public class MyFirstBean implements MyBean {
}
#Component
public class MySecondBean implements MyBean {
}
#Component
public class OtherBean {
// this way spring will inject instance of MyFirstBean
#Autowired
final MyBean myFirstBean ;
}
Solution 2 :
Sometimes i like to manually assign beans. So i autowire all available beans into list like so, and then later in #PostConstruct u do the logic :
#Autowired
private List<MyBean> myBeans;
Solution 3 :
Using #Qualifier annotation
public interface MyBean {
}
#Component("fooBean")
public class MyFirstBean implements MyBean {
}
#Component
public class MySecondBean implements MyBean {
}
#Component
public class OtherBean {
#Autowired
#Qualifier("fooBean")
final MyBean myFirstBean ;
}
Solution 4:
Custom annotation
#Qualifier
#Target({
ElementType.FIELD, ElementType.METHOD, ElementType.TYPE,
ElementType.PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
public #interface MyBeanType {
String value();
}
public interface MyBean {
}
#MyBeanType("fooBean")
#Component()
public class MyFirstBean implements MyBean {
}
#MyBeanType("barBean")
#Component
public class MySecondBean implements MyBean {
}
#Component
public class OtherBean {
#Autowired
#MyBeanType("Foo")
final MyBean myBean ;
}
Although the asker wants to avoid writing a Configuration class, I implemented a solution using one and I want to show that it's really not so bad.
Here is my Configuration class:
#Configuration
public class ApplicationContextOtherBeanQualifier {
#Autowired
#Qualifier("myFirstBean")
private MyBean myFirstBean;
#Autowired
#Qualifier("mySecondBean")
private MyBean mySecondBean;
// Here is how you get two different instances of OtherBean
// while using the same implementation:
#Bean
public OtherBean otherBeanUsingFirstBean() {
return new OtherBean(myFirstBean);
}
#Bean
public OtherBean otherBeanUsingSecondBean() {
return new OtherBean(mySecondBean);
}
}
Now, you can fit this into your Desired Situation using the #Resource and #Qualifier annotations:
#Component
public class SomeBean {
#Resource
#Qualifier("otherBeanUsingFirstBean")
private OtherBean otherBeanUsingFirstBean; // internally autowires MyFirstBean
#Resource
#Qualifier("otherBeanUsingSecondBean")
private OtherBean otherBeanUsingSecondBean; // internally autowires MySecondBean
}
Please try this out and let me know if it works for you!
You can add #Qualifier to your beans to distinguish between the different beans. When injecting the beans you can use the specified qualifier to inject the right one.
If the code should look exactly like the OP has described, custom annotations will suffice:
#Qualifier("myFirstBean")
#Retention(RetentionPolicy.RUNTIME)
public #interface FirstBeanQualifier {}
#Qualifier("mySecondBean")
#Retention(RetentionPolicy.RUNTIME)
public #interface SecondBeanQualifier {}
#Component
public class OtherBean {
private final MyBean myBean1;
private final MyBean myBean2;
public OtherBean(#FirstBeanQualifier MyBean myBean1,
#SecondBeanQualifier MyBean myBean2) {
this.myBean1 = myBean1;
this.myBean2 = myBean2;
}
}
I think this can be the simplest thing one could do.
Create a processor requesting for an object of type MyBean
#Component
public class ProcessorFactory {
#Autowired private MyFirstBean myFirstBean;
#Autowired private MySecondBean mySecondBean;
public MyBean getProcessor(arg) {
if (arg == SomeValue1) {
return myFirstBean;
}else{
return mySecondBean;
}
}
}
The usage class would look something like this
#Service
public class SomeServiceClass{
#Autowired private ProcessorFactory processorFactory;
//Other dependencies
void doSomething(Some args){
MyBean = processorFactory.getProcessor(arg);
//Do something with the object
}
}
I have two beans with the type InterfaceA.
I was trying to inject the bean into an argument of a #Bean method using #Qualifier to autowire by name.
I was surprising that Spring can't resolve the proper bean unless your parameter name is matching the bean name.
I was trying:
#Component
public class ClassA implements InterfaceA {
}
#Component
public class ClassB implements InterfaceA {
}
#Configuration
public class AppConfig {
#Bean
#Autowired
#Qualifier("classA")
public SomeOtherClass someOtherClass(InterfaceA object) {...}
}
But got the NoUniqueBeanDefinitionException.
However if I use parameter name matching the component name it works fine.
#Configuration
public class AppConfig {
#Bean
#Autowired
public SomeOtherClass someOtherClass(InterfaceA classA) {...}
}
Could someone explain why I can't use autowiring by name with #Resource or #Qualifier here?
Add the #Qualifier annotation to the parameter not to the method:
public SomeOtherClass someOtherClass(#Qualifier("classA") InterfaceA object) {...}
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 8 years ago.
When I create my ApplicationContext the myBean Constructors are used successfully.
But after creation the beans are null using #Autowired tag.
I though #Autowired would replace getBean() somehow? Am I getting this wrong?
Why do I need to call GetBean, when I already created my Beans (during ApplicationContext startup) and also Autowired them?
Here is what I have done so far:
Main:
#EnableAutoConfiguration
#Configuration
#ComponentScan("com.somePackage")
public class Main {
ApplicationContext ctx= new AnnotationConfigApplicationContext(AppConfig.class);
SomeBean myBean = ctx.getBean(SomeBean.class);
myBean.doSomething();//succeeds
AnyOtherClass aoc = new AnyOtherClass();//Nullpointer (see AnyOtherClass.class for details)
}
AnyOtherClass:
public class AnyOtherClass {
#Autowired
protected SomeBean someBean;
public AnyOtherClass(){
someBean.doSomething();//Nullpointer
}
AppConfig:
#Configuration
public class AppConfig {
#Bean
#Autowired
public SomeBean BeanSomeBean() {
return new SomeBean();
}
}
MyBean:
public class SomeBean {
public SomeBean (){}
public void doSomething() {
System.out.println("do Something..");
}
}
Note: Interface ApplicationContextAware works fine but without #Autowired. And I would really like to go with #Autowired since it sounds more comfortable and less errorprone to me.
For #Autowired to work in AnyOtherClass, AnyOtherClass needs to be a Spring bean.
Something like this
AppConfig
#Configuration
public class AppConfig {
#Bean
#Autowired
public SomeBean BeanSomeBean() {
return new SomeBean();
}
#Bean
#Autowired
public AnyOtherClass BeanAnyOtherClass() {
return new AnyOtherClass();
}
}
Main
#EnableAutoConfiguration
#Configuration
#ComponentScan("com.somePackage")
public class Main {
ApplicationContext ctx= new AnnotationConfigApplicationContext(AppConfig.class);
SomeBean myBean = ctx.getBean(SomeBean.class);
myBean.doSomething();//succeeds
AnyOtherClass aoc = ctx.getBean(AnyOtherClass.class);
}
If you instantiate a class using new AnyOtherClass(), it will bypass Spring and none of the annotations will work. You must get it out of Spring context in order for it to be a Spring bean.
Try
#Component
public class AnyOtherClass {
#Autowired
protected SomeBean someBean;
public AnyOtherClass(){
someBean.doSomething();//Nullpointer
}
Besides, you need to make sure this class is in com.somePackage package.
I try to implement using Spring 3.1.0.RELEASE + Hibernate to make RESTful web service followed this guy's project https://github.com/eugenp/REST
when I run my project is contain error like this.
SEVERE: Context initialization failed
*.BeanCreationException: Error creating bean with name 'userServiceController': Injection of autowired dependencies failed;
*.BeanCreationException: Error creating bean with name 'defaultUserService': Injection of autowired dependencies failed;
*.BeanCreationException: Could not autowire field: private com.cloudlb.dao.UserDAO com.cloudlb.service.DefaultUserService.userDao;
*.NoSuchBeanDefinitionException: No matching bean of type [com.cloudlb.dao.UserDAO]
This is my configuration: (persistence.properties)
ApplicationConfig:
#Configuration
#ComponentScan(basePackages = "com.cloudlb", excludeFilters = { #ComponentScan.Filter(Configuration.class)})
public class ApplicationConfig {
#Bean
public static PropertyPlaceholderConfigurer properties() {
final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
final Resource[] resources = new ClassPathResource[]{new ClassPathResource("persistence.properties"), new ClassPathResource("restful.properties")};
ppc.setLocations(resources);
ppc.setIgnoreUnresolvablePlaceholders(true);
return ppc;
}
In PersistenceHibernateConfig contain like this:
#Profile("hibernate")
#EnableTransactionManagement
public class PersistenceHibernateConfig { ...
#Bean
public LocalSessionFactoryBean alertsSessionFactoryBean() { ...
#Bean
public DataSource restDataSource() { ...
#Bean
public HibernateTransactionManager transactionManager() { ...
WebConfig:
#Configuration
#EnableWebMvc
public class WebConfig { ... }
So, it start get an error in autowired from here:
UserServiceController:
#Controller
public class UserServiceController {
#Autowired
private UserService userService;
UserService which is implemented by DefaultUserService:
#Service
#Transactional(propagation = Propagation.REQUIRED)
public class DefaultUserService implements UserService {
#Autowired
private UserDAO userDao;
UserDAO:
public interface UserDAO extends GenericDAO<User> { ... }
UserHibernateDAO:
#Profile("hibernate")
public class UserHibernateDAO extends GenericHibernateDAO<User> implements UserDAO{ ... }
GenericHibernateDAO:
#Profile("hibernate")
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class GenericHibernateDAO<T extends Serializable> extends AbstractHibernateDAO<T> implements GenericDAO<T> { ... }
And last one AbstractHibernateDAO:
#Transactional( propagation = Propagation.SUPPORTS )
public abstract class AbstractHibernateDAO<T extends Serializable> implements DAO<T> {
private Class<T> clazz;
#Autowired
private SessionFactory sessionFactory;
public AbstractHibernateDAO() {
super();
}
public final void setClazz(final Class<T> clazz) {
this.clazz = clazz;
}
#Override
#Transactional( readOnly = true )
public T findById(String id) {
return (T) this.getCurrentSession().get(this.clazz, id);
}
protected Session getCurrentSession() {
return this.sessionFactory.getCurrentSession();
}
}
I thought it could find UserHibernateDAO. May be I missing something here. So, hope someone know how to fix it. I struck at this problem for 2 day.
I guess there could be a problem in SessionFactory too. Because I start to fix that thing and this came up.
Thank you in advance.
In addition to #Profile("hibernate") the UserHibernateDAO needs an annotation declaring it a Spring bean like #Named or #Component.