Spring-IOC

Spring-IOC个人笔记

1、简介

​ Spring是一个开放源代码的设计层面框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

特点

  1. 开源免费
  2. 轻量级、非入侵式(小而美)
  3. 容器大杂烩,可以整合很多种框架

参考文档连接:

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

2、IOC的理解

​ IOC(控制反转),从字面上感觉神秘,但一个set()方法却能很好地解释这个概念。不过IOC并不止是set()

​ 以下基于dao层和service层之间的关系进行IOC的理解:一般而言,service层由于需要从数据库中获得数据,不可避免地需要通过dao层去访问数据库,这两者之间就形成了关联。对于关联关系的处理,不同的做法就会产生不同的结果,比如下面两种方式,仅仅因为一个set()方法,产生的效果却大不相同:

方式1

  • dao层

    package com.zero.dao;
    
    /**
     * 模拟数据库dao层接口
     */
    public interface SqlDao {
    
        /**
         * 输出一条信息
         */
        void getMessage();
    }
    
    package com.zero.dao;
    
    /**
     * SqlDao的实现类1---->MySqlDao
     */
    public class MySqlDao implements SqlDao {
    
        /**
         * 实现方法
         */
        public void getMessage() {
            System.out.println("MySql的Dao实现");
        }
    }
    
    package com.zero.dao;
    
    /**
     * SqlDao的实现类2---->OracleDao
     */
    public class OracleDao implements SqlDao {
        public void getMessage() {
            System.out.println("Oracle的dao实现");
        }
    }
    
  • service层

    package com.zero.service;
    
    /**
     * 关于sql的service层接口
     */
    public interface SqlService {
    
        /**
         * 用于调用SqlDao层的接口方法,获得消息输出
         */
        void getMessage();
    }
    
    package com.zero.service;
    
    
    import com.zero.dao.MySqlDao;
    import com.zero.dao.SqlDao;
    
    /**
     * SqlService的实现类
     */
    public class SqlServiceImpl implements SqlService {
    
        //关联一个SqlDao对象并直接初始化MySqlDao对象
        private SqlDao sqlDao = new MySqlDao();
    
        public void getMessage() {
            //调用SqlDao的接口方法获得输出
            sqlDao.getMessage();
    
        }
    }
    
    
  • 客户端调用层

    import com.zero.service.SqlServiceImpl;
    import org.junit.Test;
    
    public class IocTest {
    
        @Test
        public void iocTest(){
    
            //获得service层对象
            SqlServiceImpl sqlService = new SqlServiceImpl();
    
            //调用对象获取打印消息的方法
            sqlService.getMessage();
        }
    }
    
  • 输出结果

    MySql的Dao实现
    

方式2

  • dao层

    dao层的实现依旧和上面一样
    
  • service层

    service层接口和上面的一样
    
    package com.zero.service;
    
    import com.zero.dao.MySqlDao;
    import com.zero.dao.SqlDao;
    
    /**
     * SqlService的实现类
     */
    public class SqlServiceImpl1 implements SqlService {
    
        //关联一个SqlDao对象并初始化为MySqlDao对象
        private SqlDao sqlDao = new MySqlDao();
    
        //为关联的对象提供set()方法
        public void setSqlDao(SqlDao sqlDao) {
            this.sqlDao = sqlDao;
        }
    
        public void getMessage() {
            sqlDao.getMessage();
        }
    }
    
  • 客户端调用层

    @Test
    public void iocTest1(){
        //获得service层对象
        SqlService sqlService = new SqlServiceImpl1();
    
        //调用对象获取打印消息的方法
        sqlService.getMessage();
    
        //给sqlService对象设置其他的SqlDao对象
        ((SqlServiceImpl1)sqlService).setSqlService(new OracleDao());
    
        //再调用对象获取打印消息的方法
        sqlService.getMessage();
    }
    
  • 输出结果

    MySql的Dao实现
    Oracle的dao实现
    

对比

​ 方式一,无论进行多少次调用,sqlService.getMessage()方法的调用只能获得一种dao实现类的输出,因为在编写service层接口实现时,已经将关联的对象绑死了,客户若需要使用其他的dao层实现,只能修改原来代码中绑定的对象。

​ 方式二,由于提供了SqlDao对象的set()方法,所以一开始绑定的SqlDao对象会作为调用的默认对象,在客户需要修改绑定对象时,可以使用set()方法进行改绑,从而达到不用修改原有代码,仅需在使用的时候进行set()调用即可。

结论

​ 控制反转,指的是将创建对象的控制权进行反转,不再是在一开始编码时就创建对象并绑定,而是将创建对象的权力交给使用者,让他们决定使用哪种对象。set()方法的注入就是控制反转的实现途径之一。

3、搭建Spring环境

引入相关jar包(实际上需要很多jar包,但spring-webmvc.jar会帮我们引入很多依赖jar包)

<dependencies>
    <!-- spring-webmvc包,该包会自动去导入其他需要的依赖jar -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.0.RELEASE</version>
    </dependency>
    <!-- junit -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

编写环境

  • dao层
package com.zero.dao;
/**
 * 模拟数据库dao层接口
 */
public interface SqlDao {

    /**
     * 输出一条信息
     */
    void getMessage();
}

package com.zero.dao;

/**
 * SqlDao的实现类1---->MySqlDao
 */
public class MySqlDao implements SqlDao {

    /**
     * 实现方法
     */
    public void getMessage() {
        System.out.println("MySql的Dao实现");
    }
}
package com.zero.dao;

/**
 * SqlDao的实现类2---->OracleDao
 */
public class OracleDao implements SqlDao {
    public void getMessage() {
        System.out.println("Oracle的dao实现");
    }
}
  • service层
package com.zero.service;

/**
 * 关于sql的service层接口
 */
public interface SqlService {

    /**
     * 用于调用SqlDao层的接口方法,获得消息输出
     */
    void getMessage();
}
package com.zero.service;


import com.zero.dao.MySqlDao;
import com.zero.dao.SqlDao;

/**
 * SqlService的实现类
 */
public class SqlServiceImpl implements SqlService {

    //关联一个MySqlDao对象并直接初始化
    private SqlDao sqlDao = new MySqlDao();

    //提供set()方法
    public void setSqlDao(SqlDao sqlDao){
        this.sqlDao = sqlDao;
    }

    public void getMessage() {
        //调用SqlDao的接口方法获得输出
        sqlDao.getMessage();

    }
}

编写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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--
        bean标签相当于new一个对象,只是将该对象托管在spring容器中,要使用时从容器获取即可,
        id表示该对象在容器中的唯一标识,class表示要创建的类对象。
        property标签相当于调用对象的set()方法,ref用于通过id引用容器中的其他bean对象
    -->

    <!-- 配置SqlServiceImpl对象 -->
    <bean id="sqlService" class="com.zero.service.SqlServiceImpl">
        <!--通过ref引用mysqlSqlDao对象-->
        <!--<property name="sqlDao" ref="mysqlSqlDao"/>-->

        <!--通过ref引用oracleSqlDao对象-->
        <property name="sqlDao" ref="oracleSqlDao"/>
    </bean>

    <!-- 配置MySqlDao对象 -->
    <bean id="mysqlSqlDao" class="com.zero.dao.MySqlDao"/>

    <!-- 配置OracleDao对象 -->
    <bean id="oracleSqlDao" class="com.zero.dao.OracleDao" />

</beans>

使用测试

import com.zero.service.SqlService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {

    @Test
    public void springTest(){

        //获取Spring容器
        ApplicationContext context = new ClassPathXmlApplicationContext("application-config.xml");

        //通过容器中的id获取bean对象
        SqlService sqlService = (SqlService) context.getBean("sqlService");

        //调用bean对象的方法
        sqlService.getMessage();
    }

}

测试结果

<!--通过ref引用oracleSqlDao对象时,输出如下-->
<property name="sqlDao" ref="oracleSqlDao"/>

Oracle的dao实现
<!--通过ref引用mysqlSqlDao对象时,输出如下-->
<property name="sqlDao" ref="mysqlSqlDao"/>
    
MySql的Dao实现

4、IOC的依赖注入方式

​ spring中实现IOC(控制反转)的方式主要有以下几种方式,使用类的构造器进行注入、使用类的set方法进行注入、使用命名空间的方式注入(本质上是以上两种注入方式的简化)。构造器注入和set方法注入有其各自的优缺点:

优点缺点
构造器注入能够在构造对象的时候就给属性赋值,避免了空指针的问题有时候构造的属性过多时,这种注入方式显得麻烦;另外构造注入难以实现后期对象的属性的修改。
set注入能够依据需要,只对需要的属性进行注入需要依赖空构造方法;创建对象之初可能有属性没有被赋值,可能出现空指针问题
4.1、构造器注入

​ 使用构造器进行注入,要求pojo类必须定义了该构造器,否则无法使用。构造器方式进行注入,有以下三种方式:

搭建测试环境(定义两个pojo类)

  • Address类
package com.zero.pojo;

/**
 * Address类
 */
public class Address {
    
    //地址详情
    private String detail;
    
    //邮箱编码
    private String mailCode;

    public Address(){
        
    }
    
    public Address(String detail, String mailCode) {
        this.detail = detail;
        this.mailCode = mailCode;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getMailCode() {
        return mailCode;
    }

    public void setMailCode(String mailCode) {
        this.mailCode = mailCode;
    }

    @Override
    public String toString() {
        return "Address{" +
                "detail='" + detail + '\'' +
                ", mailCode='" + mailCode + '\'' +
                '}';
    }
}
  • User类
package com.zero.pojo;

/**
 * User类
 */
public class User {

    //姓名
    private String name;

    //性别
    private int gender;

    //住址(Address类)
    private Address address;

    public User() {
    }

    public User(String name, int gender, Address address) {
        this.name = name;
        this.gender = gender;
        this.address = address;
    }

    public String getName() {
        return name;
    }

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

    public int getGender() {
        return gender;
    }

    public void setGender(int gender) {
        this.gender = gender;
    }

    public Address getAddress() {
        return address;
    }

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

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

使用构造参数名的方式进行构造

  • 配置bean
<?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">

    <!-- 使用构造参数名进行注入(使用constructor-arg标签进行注入,name代表构造方法参数名) -->
    <bean id="user" class="com.zero.pojo.User">
        <!-- 基本数据类型和String直接使用value进行赋值 -->
        <constructor-arg name="name" value="小明"/>
   <constructor-arg name="gender" value="1"/>

    <!-- pojo类型,使用ref引用其他bean进行注入 -->
    <constructor-arg name="address" ref="address"/>
</bean>

        <!-- 创建Address类对象 -->
    <bean id="address" class="com.zero.pojo.Address">
        <constructor-arg name="detail" value="广州"/>
        <constructor-arg name="mailCode" value="123456"/>
    </bean>
</beans>
  • 测试
    @Test
    public void constructorByNameTest(){

        //获得容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationConfig.xml");

        //获得bean对象
        User user = context.getBean("user", User.class);

        //输出
        System.out.println(user);

    }
  • 结果
User{name='小明', gender=1, address=Address{detail='广州', mailCode='123456'}}

使用构造参数下标进行构造

  • 配置
<?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">

    <!-- index代表构造方法的参数索引,其余的和name方式的一样 -->
    <bean id="user" class="com.zero.pojo.User">
        <constructor-arg index="0" value="小明"/>
        <constructor-arg index="1" value="1"/>
        <constructor-arg index="2" ref="address"/>
    </bean>

    <!-- 创建Address类对象 -->
    <bean id="address" class="com.zero.pojo.Address">
        <constructor-arg name="detail" value="广州"/>
        <constructor-arg name="mailCode" value="123456"/>
    </bean>

</beans>
  • 测试
@Test
public void constructorByIndexTest(){

    //获得容器
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

    //获得bean对象
    User user = context.getBean("user", User.class);

    //输出
    System.out.println(user);

}
  • 结果
User{name='小明', gender=1, address=Address{detail='广州', mailCode='123456'}}

使用构造参数类型进行构造

  • 配置bean
<?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">

    <!-- type代表构造方法的参数类型(要使用全限定类型名),其余的和name方式的一样 -->
    <bean id="user" class="com.zero.pojo.User">
        <constructor-arg type="java.lang.String" value="小明"/>
        <constructor-arg type="int" value="0"/>
        <constructor-arg type="com.zero.pojo.Address" ref="address"/>
    </bean>

    <!-- 创建Address类对象 -->
    <bean id="address" class="com.zero.pojo.Address">
        <constructor-arg name="detail" value="广州"/>
        <constructor-arg name="mailCode" value="123456"/>
    </bean>

</beans>
  • 测试
@Test
public void constructorByTypeTest(){

    //获得容器
    ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");

    //获得bean对象
    User user = context.getBean("user", User.class);

    //输出
    System.out.println(user);

}
  • 结果
User{name='小明', gender=0, address=Address{detail='广州', mailCode='123456'}}

小结

  • 提倡使用前两种方式,第三种可能会出现多个参数类型相同的情况。
4.2、set注入

​ 使用set方法进行注入,要求pojo类必须提供空构造器,否则无法使用。set方式进行注入,主要针对以下几种类型进行注入:

  • 基本类型(以及String)
  • pojo类型
  • 数组
  • List
  • set
  • map
  • properties ( 指Java.util.Properties )

搭建测试环境(创建一个实体类, 包含各种属性)

package com.zero.pojo;

import java.util.*;

/**
 * Student类
 */
public class Student {

    //姓名
    private String name;

    //住址(Address类对象)
    private Address address;

    //爱好(数组类型)
    private String[] hobbies;

    //书籍(List集合)
    private List<String> books;

    //游戏(set集合)
    private Set<String> games;

    //身份卡(Map集合)
    private Map<String, String> card;

    //信息(Propertirs对象)
    private Properties info;

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

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

    public String[] getHobbies() {
        return hobbies;
    }

    public void setHobbies(String[] hobbies) {
        this.hobbies = hobbies;
    }

    public List<String> getBooks() {
        return books;
    }

    public void setBooks(List<String> books) {
        this.books = books;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", hobbies=" + Arrays.toString(hobbies) +
                ", books=" + books +
                ", games=" + games +
                ", card=" + card +
                ", info=" + info +
                '}';
    }
}

配置文件

<?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">

    <!-- 使用set方式配置bean,与构造器的方式不同,内部标签使用property -->
    <bean id="student" class="com.zero.pojo.Student">
        <!-- 基本数据类型以及String类型配置,name代表set方法后的名称,value代表赋的值 -->
        <property name="name" value="小强"/>
        
        <!-- 引用bean对象进行配置,name代表set方法后的名称,ref代表通过bean的id进行引用 -->
        <property name="address" ref="address"/>
        
        <!-- 数组类型配置,内部使用array标签进行配置,value代表数组元素的值(也可以使用ref等其他的配置引用对象等等) -->
        <property name="hobbies">
            <array>
                <value>篮球</value>
                <value>足球</value>
                <value>羽毛球</value>
            </array>
        </property>
        
        <!-- list类型配置, 内部使用list标签,其余的配置和数组的一样 -->
        <property name="books">
            <list>
                <value>水浒传</value>
                <value>三国演义</value>
                <value>红楼梦</value>
                <value>西游记</value>
            </list>
        </property>
        
        <!-- set类型配置, 内部使用set标签,其余的配置和数组的一样 -->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>BOB</value>
                <value>COC</value>
            </set>
        </property>
        
        <!-- 
            map类型配置, 内部使用map标签, 
            map标签内部使用一个entry标签代表一个键值对,entry标签的key代表键, value代表值 
        -->
        <property name="card">
            <map>
                <entry key="123456" value="132456798456456"/>
            </map>
        </property>

        <!-- 
            Properties类型配置, 内部使用props标签, 
            map标签内部使用一个prop标签代表一个键值对,prop标签的key代表键, 键的值必须写在prop标签体内
        -->
        <property name="info">
            <props>
                <prop key="age">18</prop>
                <prop key="height">179</prop>
            </props>
        </property>
    </bean>


    <!-- 创建Address类对象 -->
    <bean id="address" class="com.zero.pojo.Address">
        <constructor-arg name="detail" value="广州"/>
        <constructor-arg name="mailCode" value="123456"/>
    </bean>

</beans>

测试

@Test
public void setTest(){

    //获得容器
    ApplicationContext context = new ClassPathXmlApplicationContext("student.xml");

    //获得bean对象
    Student student = context.getBean("student", Student.class);

    //输出
    System.out.println(student);
}

结果

Student{
    name='小强',
    address=Address{detail='广州', mailCode='123456'},
    hobbies=[篮球, 足球, 羽毛球],
    books=[水浒传, 三国演义, 红楼梦, 西游记],
    games=[LOL, BOB, COC],
    card={123456=132456798456456},
    info={height=179, age=18}
}

注意

  • property标签内的name属性指的是setXxx()方法后的Xxx首字母小写。
4.3、使用命名空间注入

​ 命名空间注入的方式是上面两种注入方式的简化操作,主要有p命名空间注入和c命名空间注入两种,p代表property(简化set注入方式),c代表constructor(简化构造器注入方式)

使用p命名空间注入 : xmlns:p=“http://www.springframework.org/schema/p”

  1. 引入命名空间

在这里插入图片描述

  1. 使用其替代set注入

    <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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- 
            使用p命名空间进行注入,引入命名空间后,可以在bean标签属性中使用.
            p代表p命名空间, :后的为set方法后的名称, -ref代表应用其他bean的方式 -->
        <bean id="student" class="com.zero.pojo.Student" p:name="小强" p:address-ref="address"/>
    
        <!-- 创建Address类对象 -->
        <bean id="address" class="com.zero.pojo.Address">
            <constructor-arg name="detail" value="广州"/>
            <constructor-arg name="mailCode" value="123456"/>
        </bean>
    
    </beans>
    

使用c命名空间注入: xmlns:c=“http://www.springframework.org/schema/c”

  1. 引入命名空间

在这里插入图片描述

  1. 使用其替代构造器注入

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           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">
    
        <!-- 
            使用c命名空间进行注入,引入命名空间后,可以在bean标签属性中使用.
            c代表c命名空间, :后的为构造器的参数名称, -ref代表应用其他bean的方式 
        -->
        <bean id="user" class="com.zero.pojo.User" c:name="小强" c:gender="0" c:address-ref="address"  />
    
        <!-- 创建Address类对象 -->
        <bean id="address" class="com.zero.pojo.Address">
            <constructor-arg name="detail" value="广州"/>
            <constructor-arg name="mailCode" value="123456"/>
        </bean>
    </beans>
    

5、spring的配置

5.1、bean

​ 用于配置需要spring容器进行创建和托管的bean对象,使用方式参照上面的诸多例子。bean标签内提供了很多属性来设置该bean特性,主要有以下这些:

属性作用取值默认值
id唯一标识一个bean随意
name作为bean的别名,可存在多个(使用" ", ","等分隔)随意
autowire自动装配byName | byType | no | default | constructorno
scopebean的生命周期范围(可指定单例、原型模式等等)singleton | prototype | request | session | …singeleton
lazy-initbean对象懒加载false | true | defaultfalse
5.2、alias

​ 用于给创建的bean对象取别名。

使用方式

<!-- name用于绑定以配置的bean对象id, alias代表新取得别名 -->
<alias name="user" alias="u"/>
5.3、import

​ 用于引入其他的bean.xml文件并合并为一个总的配置文件

使用方式

<!-- resources用于指定配置文件得路径 -->
<import resource="beans.xml"/>

6、自动装配

​ 自动装配是指在依赖注入时,让spring容器自动去寻找已经存在的bean对象来装配现在配置的新bean对象。其使用的步骤如下:

  1. 构造环境
  • Cat类

    package com.zero.pojo;
    
    /**
     * Cat类
     */
    public class Cat {
    
        public void shout(){
            System.out.println("miaomiao~~~");
        }
    }
    
  • Dog类

    package com.zero.pojo;
    
    /**
     * Dog类
     */
    public class Dog {
    
        public void shout(){
            System.out.println("wangwang~~~");
        }
    }
    
  • Person类

    package com.zero.pojo;
    
    /**
     * Person类
     */
    public class Person {
    
        //名字
        private String name;
    
        //Dog对象
        private Dog dog;
    
        //Cat对象
        private Cat cat;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Dog getDog() {
            return dog;
        }
    
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    
        public Cat getCat() {
            return cat;
        }
    
        public void setCat(Cat cat) {
            this.cat = cat;
        }
    }
    
  1. 在配置bean时,使用bean标签的属性进行开启自动装配
<?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">

    <!-- 配置Cat对象 -->
    <bean id="cat" class="com.zero.pojo.Cat"/>
    
    <!-- 配置Dog对象 -->
    <bean id="dog" class="com.zero.pojo.Dog"/>


    <!--使用byName方式进行自动装配 -->
    <bean id="person" class="com.zero.pojo.Person" autowire="byName"/>
    
    <!-- 使用byType方式进行自动装配 -->
    <!--<bean id="person" class="com.zero.pojo.Person" autowire="byType"/>-->
</beans>

注意

  1. byName方式要求容器中已经存在id和配置属性名字相同的bean,容器会根据属性的名字去找到对应id的bean.(准确的说不是属性的名字,而是setXxx()后的Xxx首字母小写的名称)
  2. byType方式要求容器中只存在同种类型的bean对象只有一个,否则会报错。
  3. 对于容器中没有的bean,会默认不装配

7、基于注解的spring配置

​ 参考xml配置文件的方式,使用注解的方式来替代xml配置文件中所能做的一切事情。

7.1、使用@Configuration注解替代xml配置文件
package com.zero.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

//@Configuration代表将该类注解为一个配置类
@Configuration

//@ComponentScan( value = {"com.zero.pojo"}) 代表扫描指定包下的注解,value是一个数组
@ComponentScan( value = {"com.zero.pojo"})
public class Config {

}

解释:

  1. @Configuration将类注解为一个配置类,相当于一个容器空壳。
  2. @ComponentScan( value = {“com.zero.pojo”}) 用于扫描value数组中的包,扫描包内的bean配置,将其放置到容器中。
7.2、使用@Component注解替代xml配置文件中的< bean >标签
package com.zero.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * User类
 */
//@Component 代表将该类配置到spring容器中,有容器进行托管,相当于一个bean
@Component
public class User {

    //名字
   // @Value("zero")
    private String name;

    @Autowired
    private Dog dog;

    public String getName() {
        return name;
    }

    @Value("zero")
    public void setName(String name) {
        this.name = name;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", dog=" + dog +
                '}';
    }
}


注意

  1. @Component(value = “…”), value代表bean在容器中的id, 不写则为类名首字母小写。

  2. 该注解有以下几个衍生注解(意义一样,只是为了区别不同的使用场合)

    • @Repository : 用于dao层的注解
  • @Service:用于service层的注解
    • @Controller:用于controller层的注解
  1. 也可以使用@Bean注解在配置类中定义方法来代替<bean>标签
//value代表bean id, 缺省情况下为方法名
@Bean(value = "dog")
public Dog getDog(){
    return new Dog();
}
7.3、使用@value注解替代bean中的基本数据类型的注入
//名字
//@Value("zero") 代表为该基本数据类型属性注入一个值
@Value("zero")
private String name;

注意

  • 该注解可以用于属性和set方法中
7.4、使用@Autowird@Requried注解代替以注入bean对象
//使用@Autowired自动装配bean对象
@Autowired
private Dog dog;

注意

  1. @Autowired(required = false),其属性required代表该属性是否必须,true表示必须要,默认为true, false表示容器中不存在时可以为空
  2. @Autowired可以结合@@Qualifier(value = “…”) 来查找指定id的bean对象,value为bean id。
  3. 该注解可以用于属性和set方法中
7.5、使用新的方式加载注解类来代替加载xml配置文件

​ 相比于配置文件使用ClassPathXmlApplicationContext类来加载配置文件,使用配置类的方式则使用AnnotationConfigApplicationContext类来加载配置属性,其他操作就没什么区别。如下:

@Test
public void test(){
    //使用AnnotationConfigApplicationContext类来加载配置类
    ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);

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

    user.getDog().shout();
}

小细节

可以采用半配置文件半注解的方式来进行Spring的配置,不过需要引入context命名约束、开启注解支持、以及配置扫描含注解的包(扫描bean)

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

   <!-- 开启注解支持 -->
   <context:annotation-config/>

    <!-- 扫描对应包内的注解 -->
    <context:component-scan base-package="com.zero.pojo"/>

</beans>
7.6、其他一些注解
  • @Import: 用于引入另一个类的bean配置
  • @ComponentScan: 扫描一个包内的bean配置
  • @Bean:用于主配置类中配置bean
  • @Scope: 用于标注bean对象的作用域

== 新手上路,恐有错漏,望客官看看即可,还得参照各路大神博文,以免被我误入歧途。==

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值