Spring constructor dependency injection - with vs. without autowired

試著忘記壹切 提交于 2019-12-23 04:29:56

问题


I had encountered a problem described in this question, which I've already resolved by adding @Autowired annotation to constructor. Now I wonder, why it helped. What is a difference between

public RegistrationController(UserDao userDao) {
    this.userDao = userDao;
}

and

@Autowired
public RegistrationController(UserDao userDao) {
    this.userDao = userDao;
}

In both cases, userDao is injected to Controller. Only difference I discovered is that entityManager tagged with @persistenceContext annotation is injected into userDao only in the second example. But I don't know why. Any clues? And is there any other differences?

EDIT: my servlet context looks like this:

<beans  xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 
    Adds some default beans (HandlerAdapter, HandlerMapping, Binding Initializer...). It also turn on some annotations. 
    Explanation in https://stackoverflow.com/questions/28851306/spring-framework-what-is-the-purpose-of-mvcannotation-driven

    WITHOUT THIS, @RequestMapping ANNOTATIONS ARE LOADED, BUT MAPPING DO NOT WORK!!
    -->
    <mvc:annotation-driven />

<!--    Set loading annotations from classes
    <context:component-scan base-package="com.fido.pia"/>-->

    <!--manual homepage-->
    <mvc:view-controller path="/" view-name="home"/>

    <!--view resolver-->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!--static resources - request will be handeled by ResourceHttpRequestHandler-->
    <mvc:resources mapping="/resources/**" location="/resources/" />

    <!--database config-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/pia" />
        <property name="username" value="root" />
        <property name="password" value="" />
    </bean>

    <!--entity manager factory-->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="packagesToScan" value="com.fido.pia.*/**" />
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <!--<property name="generateDdl" value="true" />-->
                <property name="showSql" value="true" />
            </bean>
        </property>
    </bean>

    <!-- Transactions -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <!-- enable the configuration of transactional behavior based on annotations -->
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!--Set loading annotations from classes-->
    <context:component-scan base-package="com.fido.pia"/>
</beans>

Edit 2: Controller:

package com.fido.pia;

import com.fido.pia.dao.UserDao;
import com.fido.pia.model.User;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/register")
public class RegistrationController {

    private UserDao userDao;

    @Autowired
    public RegistrationController(UserDao userDao) {
        this.userDao = userDao;
    }

    @RequestMapping(method = RequestMethod.POST)
    @Transactional
    public void registrationSubmit(HttpServletRequest request, HttpServletResponse response) 
            throws IOException{
        String username = request.getParameter("first_name");

        userDao.save(new User("test"));

        response.sendRedirect("/");
    }
}

Dao:

package com.fido.pia.dao;

import com.fido.pia.model.User;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;


@Repository
public class UserDao {

    @PersistenceContext
    protected EntityManager entityManager;

    public User save(User row) {
        if(row.isNew()) {
            entityManager.persist(row);
            return row;
        } else {
            return entityManager.merge(row);
        }
    }   
}

回答1:


Exist two forms for injection most use of the objects!

- First 
  @Autowired, 
 - Second in constructor 
 @Autowired
 constructor(Object object)
 - other
 @Autowired
 setObjectMehod(Object object)

When an interface is implemented for more than two objects, it is necessary to qualify the object to be inserted.

Always every object that is to be injected into a component, the most common @Repository, @Services, @Controller and @Component each with its proper scope.

Injections have the same purpose are only different ways and needs as needed by the object



来源:https://stackoverflow.com/questions/34687845/spring-constructor-dependency-injection-with-vs-without-autowired

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!