Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need a setter for autowired / injected field?

I have a bean:

    <bean id="BasketLogic" class="efco.logic.EfcoBasketLogic" autowire="byType">
        <property name="documentLogic" ref="DocumentLogic" />
        <property name="stateAccess" ref="StateAccess" />
        <property name="contextAccess" ref="ContextAccess" />
    </bean>

  <bean id="EfcoErpService" autowire="byType" class="efco.erp.service.EfcoErpServiceImpl">
    <constructor-arg ref="ErpConnector"/>
  </bean>

documentLogic, stateAccess and contextAccess are fields on BasketLogicImpl

And I do not have <context:component-scan />

EfcoBasketLogic.java:

public class EfcoBasketLogic extends BasketLogicImpl {

        @Inject
        private EfcoErpService erpService;
    ...
    ...
    ...
}

erpService is null, unless I provide a setter. But why? I thought a setter isn't needed where autowiring is taking place? Could it be that BasketLogicImpl is responsible for that?

like image 887
GarfieldKlon Avatar asked Nov 02 '12 10:11

GarfieldKlon


People also ask

Why do we need setter injection?

Setter-based DI helps us to inject the dependency only when it is required, as opposed to requiring it at construction time. Spring code generation library doesn't support constructor injection so it will not be able to create proxy. It will force you to use no-argument constructor.

Is @autowired setter injection?

@Autowired annotation is optional for constructor based injection. Here, the person object from the container is passed to the constructor while creating the Customer object. The setter method will be called with the Person object at runtime by the container.

When should setter injection be used?

Use Setter injection when a number of dependencies are more or you need readability. Use Constructor Injection when Object must be created with all of its dependency.

Is Field injection same as setter injection?

Field Injection uses reflection to set the values of private variables. Constructor Injection happens at the time of creating the object itself. Setter Injection uses setters to set the value.


2 Answers

You need to use a setter because annotations are not detected unless spring is told so through either <context:component-scan /> or <context:annotation-config />. Setter is detected because you specified autowire="byType".

You may find this question and answer helpful as well: When to use autowiring in Spring

like image 93
mrembisz Avatar answered Oct 21 '22 02:10

mrembisz


First of all, the use of <context:component-scan /> or <context:annotation-config /> enables Spring to scan your code for eligible beans to meet dependencies, which will greatly improve it's ability to wire them up correctly, so I suggest adding them to your context file.

Second, you should be aware that @Inject is a standard (meaning JSR-330 specification) annotation. It is okay to mix and match Spring annotations with standard ones, but behavior may vary when doing so. @Named is commonly paired with @Inject to match components with dependencies (both JSR-330). See this reference for details, and refer to Table 4.6 for usage comments.

But to directly answer your question, "why do I need a setter when not using component-scan", is because you are not using component-scan. You are asking Spring to inject a dependency "byType", but not allowing Spring to scan your code for components which are of that type. The reason the setter works is that the type of the setter argument being injected can be discovered by Spring in the compiled bytecode (i.e. meta-data), and so it successfully resolves your request.

like image 24
pmhargis Avatar answered Oct 21 '22 04:10

pmhargis