Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @Autowired on a class new instance

I'm not so familiar with Spring and I have the following situation:

A repository class:

@Repository
public class MyRepository {
    // ...
}

A class that uses the repository class:

public class MyClass extends AbstractClass {

    @Autowired
    private MyRepository myRepository;

    //...
}

I know that if I annotate my MyClass with @Component and use it with an @Autowired, then the @Autowired MyRepository is resolved just fine. Problem is I am in a situation that I need to create new instances of MyClass with reflection. So MyRepository is never resolved and is null all the time.

Is there a way to use @Autowired in this situation?

Explaining better my situation: I have some implementations of AbstractClass. In a setup phase of my application I create a HashMap of these implementations. Basically:

{"MyClass", MyClass.class}
//...

Then I have a generic Controller that maps to the url /{class}?options=... Using the {class} @PathVariable, the HashMap above and reflection I am able to create a instance of a class based on the given options (this part is important). Do you guys think there's a better way of doing this?

Thanks in advance

like image 924
João Menighin Avatar asked Sep 16 '18 14:09

João Menighin


People also ask

Does Autowired create a new instance?

When you autowire a prototype bean, Spring will initialize a new instance of the bean. If you autowire the bean in multiple places, then Spring will create a new instance for every place you autowire the bean.

How do you Autowire a class in Spring?

We can also use @Autowired annotation on constructor for constructor based spring autowiring. For @Autowired annotation to work, we also need to enable annotation based configuration in spring bean configuration file. This can be done by context:annotation-config element or by defining a bean of type org.

How do you Autowire in normal class?

1) When you use @Component you have to make sure that the class is scanned by a component scan. It depends on how you bootstrap your applciation, but you can use <context:component-scan base-package="com. myCompany. myProject" /> for XML config or @ComponentScan for java configuration.

Does Autowired create a singleton?

Dependency injection in Spring facilitates development. You can simply put @Autowired annotation, followed by visibility tag and object, to can use every object managed by Spring context. But beware, all of these objects are a kind of Spring-managed singleton.

Can spring autowire a static interface class in Java?

Spring Autowire a Static Interface class 0 Not able to autowire a bean in task scheduler class in Java 11 Junit @AfterClass (non static) 3 Using Java Spring injection with `public static final` objects (for Jakarta Unstandard) 1 Autowired field is null in spring boot application 1

What is @AutoWired annotation in spring spring?

Spring @Autowired Annotation. The @Autowired annotation provides more fine-grained control over where and how autowiring should be accomplished. The @Autowired annotation can be used to autowire bean on the setter method just like @Required annotation, constructor, a property or methods with arbitrary names and/or multiple arguments.

When @AutoWired dependencies are available in Spring Boot?

When a bean is being constructed, the @Autowired dependencies should be available. Otherwise, if Spring cannot resolve a bean for wiring, it will throw an exception.

Is @AutoWired field is null in Spring Boot?

Autowired field is null in spring boot application 1 Spring Boot - inject static map from application.yml Related 1933 Java inner class and static nested class 221 Spring @Autowired usage 178 Can you use @Autowired with static fields? 420 @Resource vs @Autowired 752 What is the difference between @Inject and @Autowired in Spring Framework?


2 Answers

Spring itself offers some functionality for doing auto-wiring in your objects which you created by new or newInstance() or whatever.

To use it you need an AutowireCapableBeanFactory which you get by Spring's normal dependency injection with @Autowired.

@Autowired
private  AutowireCapableBeanFactory autowireCapableBeanFactory;

Then you use its autowireBean(Object) method to inject the @Autowired properties into your bean.

Object myBean = map.get(className).newInstance();
autowireCapableBeanFactory.autowireBean(myBean);

Design note:

Think well if you really need the approach above. The javadoc of AutowireCapableBeanFactory advises against using this interface for most use-cases:

This subinterface of BeanFactory is not meant to be used in normal application code: stick to BeanFactory or ListableBeanFactory for typical use cases.

Integration code for other frameworks can leverage this interface to wire and populate existing bean instances that Spring does not control the lifecycle of. This is particularly useful for WebWork Actions and Tapestry Page objects, for example.

like image 137
Thomas Fritsch Avatar answered Sep 23 '22 13:09

Thomas Fritsch


You can use Factory Design Pattern over here.

This might seem a little complicated in start but I am sure you will love it after you have implemented it.

Steps:

  1. Add @Component on all implementations of AbstractClass.
  2. Create a factory class as:

    @Component
    public class MyFactory {
    
        private final Map<String, AbstractClass> impletationMap = new HashMap<>();
    
        @Autowired
        ApplicationContext context;
    
        @PostConstruct
        public void initialize() {
            populateDataMapperMap(context.getBeansOfType(AbstractClass.class).values().iterator());
        }
    
        private void populateDataMapperMap(final Iterator<AbstractClass> classIterator) {
            while (classIterator.hasNext()) {
                AbstractClass abstractClassImpl = (AbstractClass) classIterator.next();
                impletationMap.put(abstractClassImpl.getClass().getName(), abstractClassImpl);
    
            }
        }
    }
    

When the Bean of this MyFactory class is initialized, then it will lookup for all beans of type AbstractClass and put them in the HashMap(implementationMap).

Now from this factory you can get the HashMap and then get the implementations as and when you require. It will be very easy when you add new implementation of AbstractClass as factory will take care of it.

like image 36
Rishabh Agarwal Avatar answered Sep 20 '22 13:09

Rishabh Agarwal