Spring学习(一)—Spring Framwork入门/IoC思想和DI/基于注解的注入方式

  • Post author:
  • Post category:其他




Spring学习(一)—Spring Framwork入门/IoC思想和DI/基于注解的注入方式



1. Spring Framwork入门



2002年



Rod Johnson

首次推出了Spring Framwork的前身

Interface21



2003年

,Spring Framwork公司以Interface21为基础,进行重新设计并发布了

Spring Framwork

的1.0正式版。

​ 值得一提的是

Rod Johnson

不仅是软件开发领域的大牛,他在悉尼大学还获得了

音乐学的博士学位

我们来看看Spring的官网https://spring.io/,这画风可以说是非常大艺术家了。I like it~

在这里插入图片描述

​ 在官网的Projects中可以找到Spring Framework,点击进入,可以看到目前Spring Framework已经更新到了5.1.8版本,考虑到新版本一般都不咋稳定,这里选择4.3.9版本进行学习(emmmm…其实是老师推荐使用这个版本,大概是由于目前这个版本在企业中应用的比较广泛)。

附官方参考文档

https://docs.spring.io/spring/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/


Git托管地址:

https://github.com/spring-projects/spring-framework


在这里插入图片描述

​ 现在,正式开始学习~

​ 首先,先来研究一下,Spring Framwork到底是什么?官方文档是这么说的,Spring Framework是一个Java平台,为开发Java应用程序提供全面的基础架构支持。

​ Spring Framework是一个分层架构,由7个定义良好的模块组成。组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。
在这里插入图片描述

​ 每个模块的功能如下:

  • Spring模块构建在核心容器

    Spring Core

    之上,核心容器定义了创建、配置和管理bean的方式。核心容器的主要组件是

    BeanFactory

    ,它是工厂模式的实现。

    BeanFactory

    使用

    控制反转 (IOC) 模式

    将应用程序的配置和依赖性规范与实际的应用程序代码分开。

  • Spring Context

    是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。

  • Spring AOP

    :通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

  • Spring DAO

    :JDBC DAO 抽象层提供了有意义的

    异常层次结构

    ,可用该结构来

    管理异常处理和不同数据库供应商抛出的错误消息

    。异常层次结构

    简化了错误处理

    ,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

  • Spring ORM

    :Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

  • Spring Web 模块

    :Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

  • Spring MVC 框架

    :Spring MVC (Model View Controller)框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

​ 大多数人在学习Spring之前,应该都已经学习了Mybatis,回顾一下Mybatis为我们做了些什么事情?简单总结一下,MyBatis通过简单的xml配置

避免了

几乎所有的

JDBC 代码



手动设置参数

,可以让Dao层专注于处理数据库的操作,专注于SQL语句的编写,获得SQL的查询结果。那么接下来,我们看看Spring可以为我们做什么?

​ 官方文档写道,作为应用程序开发人员,您可以从Spring平台中受益的示例如下:1.使Java方法在数据库事务中执行,而不必处理事务API。2. 使本地Java方法成为HTTP端点,而无需处理Servlet API。3. 使本地Java方法成为消息处理程序,而无需处理JMS API。4. 使本地Java方法成为管理操作,而无需处理JMX API。

​ 简而言之,Spring是一个轻量级的实现控制反转IoC和面向切面AOP的框架。

​ 那么,什么是IoC和AOP呢?

​ 由最原始的开发方式

单体式应用

说起:这里以操作数据库的user表单为背景,我们得从pojo层开始开发之路。

​ pojo层:编写与数据库对应的实体类User

package com.hooi.pojo;
public class User {
    private String userName;

    public User() {
    }

    public User(String userName) {
        this.userName = userName;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }
}

​ dao层:编写UserDao接口(增删改查的抽象方法)和UserDaoImpl实现类(增删改查的具体实现)

package com.hooi.dao;

public interface UserDao {
    //获取用户信息
    public abstract void getUserInfo();
}
package com.hooi.dao.Impl;

import com.hooi.dao.UserDao;

public class UserDaoMysqlImpl implements UserDao {

    public void getUserInfo() {
        System.out.println("获取MySQL用户信息");
    }
}

​ Service层:编写UserService业务接口(与dao层的方法相呼应)和UserServiceImpl 实现类(实现业务接口),

实现类需要持有与dao层相对应的实现类的引用

,才可以使Service层通过Dao层的实现类调用业务需要的相应的操作数据库的方法。

package com.hooi.service;

public interface UserService {
    //获取用户信息
    public abstract void getUserInfo();
}
package com.hooi.service;

import com.hooi.dao.UserDao;

public class UserServiceImpl implements UserService {

    private UserDao userDao = new UserDaoMySqlImpl();//Dao层实现类的引用

	//获取用户信息
    public void getUserInfo() {
        userDao.getUserInfo();//通过Dao层实现类的实例调用相应方法
    }
}

​ Servlet层:通过业务层实现类的方法处理前端传来的用户请求。

UserServiceImpl service = new UserServiceImpl();
service.getUserInfo();

​ 如果dao层想拓展一个新的UserDao实现类,比如说

UserDaoOracleImpl

。那么对应的就要修改Service层实现类中持有的Dao实现类的引用

private UserDao userDao = new UserDaoOracleImpl();

。如果dao层拓展的实现类有很多个呢?虽然对于Servlet层来说,要做的事情(相应的参数传递和调用)并不会改变,但是在Service层面,程序员将需要进行大量的代码修改和维护的工作。客户端的需求是由前端传回的,servlet层在处理请求时就可以判别需要什么样的UserDao实现类,但是却将一大堆工作交由Service层去处理,这样会导致Service层不能只专注于对业务的处理,有悖于解耦的思想。我们不妨思考一下,如何让前端去选择到底使用dao层的哪个实现类,让Service层不再管理相关对象的创建?借助于封装和面向接口编程的思想,我们可以在Service层给Servlet层留出一个接口,Service层在使用某个实现类的时候,并不去创建它,而是引用该实现类实现的接口。UserServiceImpl类中的代码可以修改为:

package com.hooi.service;

import com.hooi.dao.UserDao;

public class UserServiceImpl implements UserService {

    private UserDao userDao;//将实现类用接口封装

    public UserServiceImpl() {
    }

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

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void getUserInfo() {
        userDao.getUserInfo();
    }
}

​ 接口的具体实现类由Servlet层通过相应的set方法进行设置,这样不管前端的需求如何变化,Service层都不需要再进行大量的代码修改,只专注于处理相关业务即可。而Servlet层的操作也仅仅是增加了创建相关对象的步骤。

package com.hooi.service;

import com.hooi.dao.Impl.UserDaoMysqlImpl;
import com.hooi.dao.Impl.UserDaoOracleImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class ServiceTest {

    @Test
    public void getUserInfo(){
        UserServiceImpl service = new UserServiceImpl();
        //如果前端需要Oracle的用户数据,在servlet层为UserServiceImpl设置相应的实现类属性
        service.setUserDao(new UserDaoOracleImpl());
        service.getUserInfo();

        //如果前端需要Mysql的用户数据,在servlet层为UserServiceImpl设置相应的实现类属性
        service.setUserDao(new UserDaoMysqlImpl());
        service.getUserInfo();
    }
}

​ 但是,即便如此,当我们在一个对象里需要使用另一个对象时,我们仍然需要得到它,使用完之后还需要将它销毁(比如Connection等),这些对象始终会和其他的接口或类耦合在一起。设想,如果有一个容器可以

专门负责管理对象的生命周期和对象间的关系

,当我们想要使用一个对象时,整个过程不再由我们自己控制,而是由这个容器来完成,如果容器给我们的对象不符合我们的需求,我们只要抛出异常即可。而Spring所倡导的开发方式也是如此,

所有的类的创建、销毁都由Spring来控制,控制对象生存周期的不再是引用它的对象,而是Spring。

对于某个具体的对象而言,以前是它控制其他对象的创建,而现在所有的对象都被Spring控制,我们的程序变得更加具有

高度配置性



动态性

,这就是

Spring的核心思想IoC(Inversion of Control),控制反转。




02 IoC和DI

IoC依靠于DI(Dependency Injection,依赖注入)实现。

首先,我们使用Spring框架改造一下上面的案例。使用Spring框架先要导入jar包。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.9.RELEASE</version>
</dependency>

这里pojo层仍然使用上面的User实体类,Dao和Service层的代码依然不变。接下来我们需要编写Spring的配置文件。在resources目录下创建applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--User对象-->
    <bean id="user" class="com.hooi.pojo.User">
        <property name="userName" value="hooi"/>
    </bean>
    
    <!--UserDaoMysqlImpl对象-->
    <bean id="userDaoMysqlImpl" class="com.hooi.dao.Impl.UserDaoMysqlImpl"/>
    <!--UserDaoOracleImpl对象-->
    <bean id="userDaoOracleImpl" class="com.hooi.dao.Impl.UserDaoOracleImpl"/>

    <!--MysqlService-->
    <bean id="userServiceMysqlImpl" class="com.hooi.service.UserServiceImpl">
        <property name="userDao" ref="userDaoMysqlImpl"/>
    </bean>
    <!--OracleService-->
    <bean id="userServiceOracleImpl" class="com.hooi.service.UserServiceImpl">
        <property name="userDao" ref="userDaoOracleImpl"/>
    </bean>

</beans>

使用junit进行测试:

@Test
public void _getUserInfo(){
    //通过ClassPathXmlApplicationContext传入相应的xml文件获取想要的对象
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserServiceImpl userServiceMysqlImpl = (UserServiceImpl) context.getBean("userServiceMysqlImpl");
    userServiceMysqlImpl.getUserInfo();

    UserServiceImpl userServiceOracleImpl = (UserServiceImpl) context.getBean("userServiceOracleImpl");
    userServiceOracleImpl.getUserInfo();
    
}

测试结果:

在这里插入图片描述

使用Spring之后,我们就不需要再去Servlet层或是Service层改动大量代码,当我们想要实现不同的操作时,只需要在相应的xml配置文件中进行修改或重新注册新的Bean。以上使用的那些对象都由Spring创建,管理,装配。那么,这些对象的属性到底是如何设置值的?

接下来,我们来探究一下DI(Dependency Injection,依赖注入)。

往常我们创建对象的方式无非就两种:有参构造或无参构造。那么,我们来测试一下Spring是如何通过构造器实现依赖注入的。

首先,改造一下User实体类,以便测试。

package com.hooi.pojo;

public class User {
    private String userName;
    private String gender;
    private int age;

    public User() {
        System.out.println("无参构造");
    }

    public User(String userName) {
        System.out.println("有参构造(一)");
        this.userName = userName;
    }

    public User(String userName,String gender) {
        System.out.println("有参构造(二)");
        this.userName = userName;
        this.gender = gender;
    }

    public User(String userName,String gender,int age) {
        System.out.println("有参构造(三)");
        this.userName = userName;
        this.gender = gender;
        this.age = age;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        System.out.println("setUserName:"+userName);
        this.userName = userName;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        System.out.println("setGender:"+gender);
        this.gender = gender;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        System.out.println("setAge:"+age);
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                '}';
    }
}

测试代码:

package com.hooi.pojo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {

    @Test
    public void userTest(){

        System.out.println("----------->获取上下文");

        ApplicationContext context = new ClassPathXmlApplicationContext("userBean.xml");

        User user = (User) context.getBean("user");

        System.out.println("----------->获取对象"+user);

    }
}

Spring的相关配置文件userBean.xml

配置1:

<!--使用property对成员变量进行赋值-->
<bean id="user" class="com.hooi.pojo.User">
        <property name="userName" value="hooi"/>
</bean>

测试结果1:由测试结果可以看出property属性依赖无参构造和set方法

在这里插入图片描述

我们将User类中的无参构造方法注掉,再次测试,测试结果如下:会提示没有发现默认构造器

在这里插入图片描述

配置2:

<!--使用构造器的参数下标进行属性赋值-->
<bean id="user" class="com.hooi.pojo.User">
    <constructor-arg index="0" value="hooi2"/>
    <constructor-arg index="1" value="female"/>
</bean>

测试结果2:

在这里插入图片描述

配置3:

<!--使用构造器的参数具体名字进行赋值-->
<bean id="user" class="com.hooi.pojo.User">
    <constructor-arg name="userName" value="hooi3"/>
    <constructor-arg name="gender" value="female"/>
</bean>

测试结果3:

在这里插入图片描述

配置4:

<!--通过参数类型进行赋值-->
    <bean id="user" class="com.hooi.pojo.User">
        <constructor-arg type="java.lang.String" value="hooi4"/>
        <constructor-arg type="java.lang.String" value="female"/>
        <constructor-arg type="int" value="18"/>
    </bean>

测试结果4:在测试中遇到一些小问题,如果User类中的age的数据类型为int,千万不要在配置文件中将type属性填为Interger类型,会出现异常UnsatisfiedDependencyException。

在这里插入图片描述

以上是分开测试的结果,如果在userBean.xml中同时注册了以上所有的user对象,在获取上下文时,spring会按注册顺序将配置文件中所有的user创建出来。

测试代码:

package com.hooi.pojo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {

    @Test
    public void userTest(){


        ApplicationContext context = new ClassPathXmlApplicationContext("userBean.xml");
        System.out.println("----------->获取上下文");

        User user = (User) context.getBean("user");
        User user2 = (User) context.getBean("user2");
        User user3 = (User) context.getBean("user3");
        User user4 = (User) context.getBean("user4");

        System.out.println("----------->获取对象:"+user);
        System.out.println("----------->获取对象:"+user2);
        System.out.println("----------->获取对象:"+user3);
        System.out.println("----------->获取对象:"+user4);

    }
}

测试结果:

在这里插入图片描述

以上,我们简单的测试了通过构造器【有参构造(3种方式)和无参构造】进行依赖注入的方式。下面继续探究其他注入方式。


setter注入:

本质就是在xml文件中使用property属性,通过无参构造器和

set方法

进行注入。setter注入要求被注入的属性,必须拥有set方法,且set方法的名字必须规范(set+属性名),在测试中,属性名使用全小写并不会报错,但是,为了代码的规范性,可读性以及美观性,属性名首字母最好还是使用大写。


p命名空间注入

:实质上是使用了setter注入,但是简化了代码量,一行代码就可以搞定


c命名空间注入

实质上是使用了构造器注入。

在构造器注入的测试中,我们只测试了基本数据类型的注入,下面测试引用数据类型的注入。为了方便测试,我们重新创建一个实体类。

package com.hooi.pojo;

import java.util.*;

public class Student {
    private String name;//姓名
    private int age;//年龄
    private Address address;//地址
    private String[] books;//喜欢的书籍
    private List<String> hobbies;//爱好
    private Set<String> skills;//特长
    private String motto;//座右铭
    private Map<String,String> otherInfo;//其他信息

    public Student() {
    }

    public Student(String name, int age, Address address, String[] books, List<String> hobbies, Set<String> skills, String motto, Map<String, String> otherInfo) {
        this.name = name;
        this.age = age;
        this.address = address;
        this.books = books;
        this.hobbies = hobbies;
        this.skills = skills;
        this.motto = motto;
        this.otherInfo = otherInfo;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Student(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }
    
    public void setAge(int age) {
        this.age = age;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public void setHobbies(List<String> hobbies) {
        this.hobbies = hobbies;
    }

    public void setSkills(Set<String> skills) {
        this.skills = skills;
    }

    public void setMotto(String motto) {
        this.motto = motto;
    }

    public void setOtherInfo(Map<String, String> otherInfo) {
        this.otherInfo = otherInfo;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbies=" + hobbies +
                ", skills=" + skills +
                ", motto='" + motto + '\'' +
                ", otherInfo=" + otherInfo +
                '}';
    }
}

Spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--1. 构造器注入-->
    <!--1.1 有参构造-->
    <bean id="address1" class="com.hooi.pojo.Address">
        <constructor-arg name="address" value="陕西省西安市西安邮电大学长安校区"/>
    </bean>

    <!--1.2 无参构造-->
    <bean id="address2" class="com.hooi.pojo.Address">
        <property name="address" value="陕西省西安市西安邮电大学雁塔校区"/>
    </bean>

    <!--2. setter注入-->
    <bean id="student" class="com.hooi.pojo.Student">
        <!--2.1 基本类型注入-->
        <property name="name" value="Hooi"/>
        <property name="age" value="18"/>
        <!--2.2 Bean类型注入-->
        <property name="address" ref="address1"/>
        <!--2.3 数组类型注入-->
        <property name="books">
            <array>
                <value>小王子</value>
                <value>人间失格</value>
                <value>金阁寺</value>
                <value>白夜行</value>
            </array>
        </property>
        <!--2.4 list类型注入-->
        <property name="hobbies">
            <list>
                <value>撸猫</value>
                <value>遛狗</value>
                <value>打游戏</value>
            </list>
        </property>
        <!--2.5 set类型注入-->
        <property name="skills">
            <set>
                <value>Java编程</value>
                <value>文档撰写</value>
            </set>
        </property>
        <!--2.6 null注入-->
        <property name="motto">
            <null/>
        </property>
        <!--2.7 Map类型注入-->
        <property name="otherInfo">
            <map>
                <entry key="邮箱地址" value="xxxxxxxxxx@qq.com"/>
                <entry key="联系电话" value="18888888888"/>
            </map>
        </property>
    </bean>
    <!--3. P空间命名 需要导入约束xmlns:p="http://www.springframework.org/schema/p"-->
    <bean id="student2" class="com.hooi.pojo.Student" p:name="Hooi2" p:address-ref="address1"/>
    <!--4. C空间命名 需要导入约束xmlns:c="http://www.springframework.org/schema/c"-->
    <bean id="student3" class="com.hooi.pojo.Student" c:_0="Hooi3" c:_1="3" c:_2-ref="address2"/>
</beans>

测试代码:

package com.hooi.pojo;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class StudentTest {

    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) context.getBean("student");
        Student student2 = (Student) context.getBean("student2");
        Student student3 = (Student) context.getBean("student3");
        System.out.println(student);
        System.out.println(student2);
        System.out.println(student3);
    }
}

测试结果:在测试c命名空间注入方式时,必须根据有参构造方法的传入参数进行相应的注入,注入属性的个数要与相应的有参构造方法需要传入的参数个数一致。

在这里插入图片描述




03 基于注解的注入方式

除了以上那些注入方式,Spring还提供了更为方便的注入方式—

基于注解的注入

。一共有四个注解可以用于注册bean,每种注解可以任意使用,效果是一样的,但是语义有所差异,为了保证代码的可读性,建议按照如下方式使用:

  • @Component:可以用于注册所有bean
  • @Repository:主要用于注册dao层的bean
  • @Service:主要用于注册service层的bean
  • @Controller:主要用于注册控制层的bean


描述依赖关系

的注解主要有两种:分别是@Autowired和@Resource

Spring 2.5起引入了注解@Autowired,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。通过@Autowired的使用来消除set,get方法。但是spring的reference并不提倡这种方式,因为这种方式会

破坏模块关系的可读性

@Autowired的属性有以下六种:

  • No:不启用自动装配。这也是Autowired的默认值,引用关系显示声明。
  • byName:通过属性的名字在IoC容器中查找相应的JavaBean依赖的对象并为其注入。这种方式的本质是为setter注入。如,UserServiceImpl类中有个属性为userDao,那么指定其Autowire属性为byName后,Spring的IoC容器会在配置文件中查找id/name属性为userDao的bean,然后使用相应的setter为其注入。
  • byType:通过属性的类型查找JavaBean依赖的对象并为其注入。这也是Autowired

    默认

    的方式。同例,比如UserController类中有个属性为userServiceImpl,类型为UserServiceImpl,那么,指定其autowire属性为byType后,Spring IoC容器会查找Class属性为UserServiceImpl的bean,使用Seter方法为其注入。如果存在多个该类型bean,那就会由

    DefaultListableBeanFactory



    determineAutowireCandidate

    方法来决定具体注入哪个bean,该方法会先去找被@Primary 注解的bean,再找被@Order,@PriorityOrder注解的bean,最后再以byName的方式去匹配。如果在@Autowored()下使用了@Qualifier (“{beanName}”)注解,当匹配到多个符合该类型的bean时,不会调用

    determineAutowireCandidate

    方法,而是直接寻找@Qualifier指定的beanName去查找并注入,如果找不到会抛出异常。@Qualifier与byName方式的区别在于byName需要遍历,而前者会直接定位到相应的bean,因此使用@Qualifier的处理效率会更高。例:
public class UserController {

    @Autowired//自动装配
    @Qualifier("userServiceImpl")//注入
    private UserServiceImpl userServiceImpl;
}    
  • constructor:同byType一样,也是通过类型查找依赖对象。与byType的区别在于它不是使用Seter方式注入,而是使用构造器注入。如果容器中没有找到与构造器参数类型一致的bean,那么抛出异常。

  • autodetect:在byType和constructor之间自动的选择注入方式。通过bean类的自省机制(introspection)来决定是使用constructor还是byType方式进行自动装配。如果发现默认的构造器,那么将使用byType方式,否则采用constructor。

  • default:由上级标签的default-autowire属性确定。注意:在配置bean时,标签中Autowire属性的优先级比其上级标签高,即是说,如果在上级标签中定义default-autowire属性为byName,而在中定义为byType时,Spring IoC容器会优先使用标签的配置。

<beans beans default-autowire="byType" 	           
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="userDaoMysqlImpl" class="com.hooi.dao.Impl.UserDaoMysqlImpl"/>
	<bean id="userServiceImpl" class="com.hooi.service.UserServiceImpl" p:userDao-ref="userDaoMysqlImpl"/>
	<bean id="userController" class="com.hooi.controller.UserController" autowire="byName"/>
    
</beans>

@Resource是Java的注解,默认以byName的方式进行匹配注入,如果byType方式查找找多个符合的bean时,需要使用@Qualifier注解指定bean的具体名字。


Type" 	           
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <bean id="userDaoMysqlImpl" class="com.hooi.dao.Impl.UserDaoMysqlImpl"/>
	<bean id="userServiceImpl" class="com.hooi.service.UserServiceImpl" p:userDao-ref="userDaoMysqlImpl"/>
	<bean id="userController" class="com.hooi.controller.UserController" autowire="byName"/>
    
</beans>

@Resource是Java的注解,默认以byName的方式进行匹配注入,如果byType方式查找找多个符合的bean时,需要使用@Qualifier注解指定bean的具体名字。




版权声明:本文为yinyanyao1747原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。