Java--Spring之IoC控制反转;基于XML配置文件的DI

Posted MinggeQingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--Spring之IoC控制反转;基于XML配置文件的DI相关的知识,希望对你有一定的参考价值。

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架

控制反转Inversion of Control,缩写IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

依赖:classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA 对 classB 有依赖

控制:创建对象,给对象的属性赋值,管理对象之间的关系

反转:控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的创建,属性赋值,依赖的管理。

正转:开发人员在代码中,使用new 构造方法创建对象(主动管理对象),如下

User user = new User();

Ioc 的实现:

1、依赖注入Dependency Injection,简称DI):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系

容器全权负责的组件的装配,它会把符合依赖关系的对象通过JavaBean属性或者构造函数传递给需要的对象。

(1)设值注入(Setter Injection):通过JavaBean属性注射依赖关系的做法称为设值方法注入

(2)构造注入Constructor Injection): 将依赖关系作为构造函数参数传入的做法称为构造器注入

2、依赖查找Dependency Lookup):容器提供回调接口和上下文条件给组件

Spring 框架使用依赖注入(DI)实现 IoC

spring的IOC是使用的di实现了ioc的功能, spring底层创建对象,使用的是反射机制

spring是一个容器,管理对象,给属性赋值, 底层是反射创建对象

Spring 容器负责创建、管理所有的 Java 对象,这些 Java 对象被称为 Bean

Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”(DI)的方式来管理 Bean之间的依赖关系。使用 IoC 实现对象之间的解耦和

Java中创建对象主要有如下方式:

(1)构造方法,new对象

User user = new User();

(2)反射机制

【1】使用class的newInstance()方法

// 通过反射机制,获取Class,通过Class来实例化对象
Class className = Class.forName("com.xx.User");

// newInstance()方法会调用User类的无参数构造方法,完成对象的创建(必须保证无参构造方法是存在)
Object obj = className.newInstance();//User对象无参构造

【2】使用Constructor的newInstance()方法

Class userClass = Class.forName("reflect.xx.User");

Constructor constructor = userClass .getConstructor();
Object obj = constructor.newInstance();

(3)序列化和反序列化

/*
序列化对象
*/
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/iostream/users"));

            /**
             * 1、一次序列化多个对象
             *  将对象放到集合当中,序列化集合。
             *  参与序列化的ArrayList集合以及集合中的元素都需要实现 java.io.Serializable接口
             * 2、ArrayList 也实现了 java.io.Serializable 接口
             * public class ArrayList<E> extends AbstractList<E>
             *         implements List<E>, RandomAccess, Cloneable, java.io.Serializable
             * */
            //创建List数组
            List<Student> list = new ArrayList<>();
            User u1 = new User();
            list.add(u1);

            oos1.writeObject(list);

            oos1.flush();


/*
反序列化对象
*/
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/iostream/users"));
            // 开始反序列化,读
            List<User> list = (List<User>) ois.readObject();
            for (User user:list) 
                System.out.println(user);
            

(4)克隆

User user1 = (User) user.clone();

首先我们先设置一下maven的本地仓库

一、基于XML配置文件的DI

(一)设值注入(Setter Injection)

set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例

1、简单类型

简单类型set注入语法如下:

<bean id="xx" class="xx">
    <property name="属性名字" value="属性值" />
    ...
</bean>

注:

(1)没有set方法报错

        Bean property 'userName' is not writable or has an invalid setter method

(2)有set方法没赋值 不报错,值为null;UseruserName='null', age=18

(3)没有email属性,但是有setEmail方法,不会报错,该属性值不存在

(4)spring还可以创建非自定义对象,如 java.util.Date

(1)创建一个Java类对象User

public class User 
    private String userName;
    private int age;

    public User() 
        System.out.println("spring会调用User类的无参构造方法创建对象");
    

    /*
    (1)没有set方法报错
        Bean property 'userName' is not writable or has an invalid setter method
    (2)有set方法没赋值
        不报错,值为null;UseruserName='null', age=18
    (3)没有email属性,但是有setEmail方法,不会报错,该属性值不存在
    */
    public void setUserName(String userName) 
        this.userName = userName;
    

    public void setAge(int age) 
        this.age = age;
    

    //没有email属性,但是有setEmail方法,不会报错,该属性值不存在
    public void setEmail(String email) 
        System.out.println("setEmail="+email);
    

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

(2)spring配置文件 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">

    <!-- set注入(设值注入);简单类型set注入;声明User对象
        注入:赋值
        简单类型:spring中规定java的基本数据类型和String都是简单类型
        Spring 框架使用依赖注入(DI)实现 IoC;
        常用注入有两种:set注入(设值注入)、构造注入

        1、set注入(设值注入):spring调用Java类对象的set方法,在set方法中完成属性赋值
        (1)简单类型set注入
            <bean id="xx" class="xx">
                <property name="属性名字" value="属性值" />
                ...
            </bean>
    -->
    <bean id="user" class="com.mycompany.p1setinject.User">
        <!--简单类型set注入
            <bean id="xx" class="xx">
                <property name="属性名字" value="属性值" />
                ...
            </bean>

        (1)没有set方法报错
            Bean property 'userName' is not writable or has an invalid setter method
        (2)有set方法没赋值
            不报错,值为null;UseruserName='null', age=18
        (3)没有email属性,但是有setEmail方法,不会报错,该属性值不存在
        -->
        <property name="userName" value="admin" /><!-- 类似setUserName("admin") -->
        <property name="age" value="18" />
        <property name="email" value="45678545@qq.com" />
    </bean>

    <!-- bean创建非自定义对象 -->
    <bean id="myDate" class="java.util.Date">
        <property name="time" value="987657289037632" />
    </bean>

</beans>

(3)测试类

public class TestSetInject 
    @Test
    public void testSetInjectNormal()
        String config = "p1setinject/applicationContext.xml";

        ApplicationContext ac = new ClassPathXmlApplicationContext(config);

        User user = (User) ac.getBean("user");
        System.out.println(user);
    

    @Test
    public void testSetDate()
        String config = "p1setinject/applicationContext.xml";

        ApplicationContext ac = new ClassPathXmlApplicationContext(config);

        Date date = (Date) ac.getBean("myDate");
        System.out.println("myDate="+date);
    

2、引用类型

语法如下

(1)简单类型set注入
    <bean id="xx" class="xx">
        <property name="属性名字" value="属性值" />
        <property name="引用对象名称" ref="引用对象bean的id(对象的名称)" />
        ...
    </bean>

(2)引用类型set注入:spring调用类的set方法
    <bean id="xx" class="xx">
        <property name="属性名称" ref="引用对象bean的id(对象的名称)" />
    </bean>

(1)User和Address对象

public class User 
    private String userName;
    private int age;

    //声明一个引用类型
    private Address address;

    public User() 
        System.out.println("spring会调用User类的无参构造方法创建对象");
    

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

    public void setAge(int age) 
        this.age = age;
    

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

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



public class Address 
    private String name;
    private String address;

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

    public void setAddress(String address) 
        this.address = address;
    

    @Override
    public String toString() 
        return "Address" +
                "name='" + name + '\\'' +
                ", address='" + address + '\\'' +
                '';
    

(2)spring配置文件 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">

    <!-- set注入(设值注入);引用类型set注入;声明User对象
        注入:赋值
        简单类型:spring中规定java的基本数据类型和String都是简单类型
        Spring 框架使用依赖注入(DI)实现 IoC;
        常用注入有两种:set注入(设值注入)、构造注入

        1、set注入(设值注入):spring调用Java类对象的set方法,在set方法中完成属性赋值
        (1)简单类型set注入
            <bean id="xx" class="xx">
                <property name="属性名字" value="属性值" />
                <property name="引用对象名称" ref="引用对象bean的id(对象的名称)" />
                ...
            </bean>

        (2)引用类型set注入:spring调用类的set方法
            <bean id="xx" class="xx">
                <property name="属性名称" ref="引用对象bean的id(对象的名称)" />
            </bean>
    -->
    <bean id="user" class="com.mycompany.p2setinjectreference.User">
        <!--引用类型set注入:spring调用类的set方法
            <bean id="xx" class="xx">
                <property name="属性名称" ref="引用对象bean的id(对象的名称)" />
            </bean>
        -->
        <property name="userName" value="admin" /><!-- 类似setUserName("admin") -->
        <property name="age" value="18" />
        <!-- 引用类型
            <property name="属性名称" ref="引用对象bean的id(对象的名称)" />
        -->
        <property name="address" ref="myAddress" />
    </bean>

    <!--声明Address对象-->
    <bean id="myAddress" class="com.mycompany.p2setinjectreference.Address">
        <property name="name" value="家住址" />
        <property name="address" value="江南水乡" />
    </bean>

(二)构造注入Constructor Injection

spring调用类的有参构造方法,在创建对象同时,在构造方法中给属性赋值

构造注入使用 <constructor-arg> 标签

<constructor-arg>标签:一个<constructor-arg>标签表示构造方法的一个参数

<constructor-arg> 标签属性:

(1)name:表示构造方法的形参名

(2)index:表示构造方法的参数位置,参数从左往右位置是 0 , 1 ,2...

(3)value:构造方法形参是简单类型,使用value

(4)ref:构造方法形参是引用类型,使用ref

注:

(1)使用name属性实现构造注入;给形参赋值位置可以打乱,根据形参名name赋值

(2)使用index属性实现构造注入;给形参赋值位置可以打乱,根据index赋值

(3)省略index;使用index属性实现构造注入;给形参赋值位置不可以打乱

User和Address对象

public class User 
    private String userName;
    private int age;

    //声明一个引用类型
    private Address address;

    public User() 
        System.out.println("spring会调用User类的无参构造方法创建对象");
    

    /**
     * 创建有参数构造方法
     */
    public User(String userName, int age, Address address) 
        System.out.println("=====User有参数构造方法======");
        //属性赋值
        this.userName = userName;
        this.age = age;
        this.address = address;
    

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

    public void setAge(int age) 
        this.age = age;
    

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

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

spring配置文件 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对象
        注入:赋值
        简单类型:spring中规定java的基本数据类型和String都是简单类型
        Spring 框架使用依赖注入(DI)实现 IoC;
        常用注入有两种:set注入(设值注入)、构造注入

        1、set注入(设值注入):spring调用Java类对象的set方法,在set方法中完成属性赋值
        (1)简单类型set注入
            <bean id="xx" class="xx">
                <property name="属性名字" value="属性值" />
                ...
            </bean>

        (2)引用类型set注入:spring调用类的set方法
            <bean id="xx" class="xx">
                <property name="属性名称" ref="引用对象bean的id(对象的名称)" />
            </bean>

        2、构造注入:spring调用类的有参构造方法,在创建对象同时,在构造方法中给属性赋值
            构造注入使用 <constructor-arg> 标签
            <constructor-arg>标签:一个<constructor-arg>标签表示构造方法的一个参数
            <constructor-arg> 标签属性:
                name:表示构造方法的形参名
                index:表示构造方法的参数位置,参数从左往右位置是 0 , 1 ,2...
                value:构造方法形参是简单类型,使用value
                ref:构造方法形参是引用类型,使用ref
    -->

    <!--声明Address对象-->
    <bean id="myAddress" class="com.mycompany.p3constructorinject.Address">
        <property name="name" value="家住址" />
        <property name="address" value="江南水乡" />
    </bean>

    <!--(1)使用name属性实现构造注入;给形参赋值位置可以打乱,根据形参名name赋值-->
    <bean id="user" class="com.mycompany.p3constructorinject.User">
        <constructor-arg name="age" value="20" />
        <constructor-arg name="userName" value="admin" />
        <!-- 引用类型,构造方法形参是引用类型,使用ref-->
        <constructor-arg name="address" ref="myAddress" />
    </bean>

    <!--(2)使用index属性实现构造注入;给形参赋值位置可以打乱,根据index赋值-->
    <bean id="user1" class="com.mycompany.p3constructorinject.User">
        <constructor-arg index="1" value="20" />
        <constructor-arg index="0" value="root" />
        <constructor-arg index="2" ref="myAddress" />
    </bean>

    <!--(2)省略index;使用index属性实现构造注入;给形参赋值位置不可以打乱-->
    <bean id="user2" class="com.mycompany.p3constructorinject.User">
        <constructor-arg value="root" />
        <constructor-arg value="20" />
        <constructor-arg ref="myAddress" />
    </bean>

    <!-- 创建File,使用构造注入 -->
    <bean id="myFile" class="java.io.File">
        <constructor-arg name="parent" value="D:\\Java\\JavaProject\\spring-course\\spring-1" />
        <constructor-arg name="child" value="readme.txt" />
    </bean>
</beans>

(三)引用类型自动注入

引用类型属性的注入,也可不在配置文件中显示注入。可通过<bean/>标签设置 autowire 属性值,为引用类型属性进行隐式自动注入(默认是不自动注入引用类型属 性)

引用类型自动注入:spring根据某些规则给引用类型赋值;常用规则:byName;byType

1、byName:按名称自动注入

当配置文件中被调用者 bean 的 id 值与代码中调用者 bean 类的属性名相同时,可使用byName 方式,让容器自动将被调用者 bean 注入给调用者 bean。容器是通过调用者的 bean类的属性名与配置文件的被调用者 bean 的 id 进行比较而实现自动注入的

语法如下,使用autowire = "byName"

<bean id="xx" class="xx" autowire="byName">
    <property name="xx" value="xx" />
</bean>

User对象

public class User 
    private String userName;
    private int age;

    //声明一个引用类型
    private Address address;

    public User() 
        System.out.println("spring会调用User类的无参构造方法创建对象");
    

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

    public void setAge(int age) 
        this.age = age;
    

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

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

spring配置文件 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">

    <!-- 引用类型自动注入:spring根据某些规则给引用类型赋值
        常用规则:byName;byType
        1、byName(按名称注入):
            Java中引用类型的属性名和spring容器(spring配置文件)中<bean>的id名称一致
            且数据类型一致,这样spring容器中的bean就能够给属性赋值

            语法:
            <bean id="xx" class="xx" autowire="byName">
                <property name="xx" value="xx" />
            </bean>
        2、byType(按类型注入):
            Java中引用类型的数据类型和spring容器(spring配置文件)的<bean>的class属性是同源关系
           同源关系:
            (1)java类中引用类型的数据类型和bean的class的值一致
            (2)java类中引用类型的数据类型和bean的class的值是父子类关系
            (3)java类中引用类型的数据类型和bean的class的值是接口和实现类关系
           语法:
           <bean id="xx" class="xx" autowire="byType">
                <property name="xx" value="xx" />
           </bean>

           注:
           使用byName,属性是引用类型时,不用使用<property>标签,但是单独声明引用类型时
           其<bean>标签的id值需要和Java属性值名一致
    -->

    <!-- (1)byName -->
    <bean id="user" class="com.mycompany.p4referenceautobyname.User" autowire="byName">
        <property name="userName" value="admin" />
        <property name="age" value="20" />
        <!--引用类型-->
<!--        <property name="address" ref="myAddress" />-->
    </bean>

    <!--声明Address对象;因为不是使用ref指向,自动查找,需要使用Java对象的属性名-->
    <bean id="address" class="com.mycompany.p4referenceautobyname.Address">
        <property name="name" value="家住址" />
        <property name="address" value="江南水乡" />
    </bean>

</beans>

 注: 使用byName,属性是引用类型时,不用使用<property>标签,但是单独声明引用类型时 其<bean>标签的id值需要和Java属性值名一致

2、byType:按类型自动注入

使用 byType 方式自动注入,要求:配置文件中被调用者 bean 的 class 属性指定的类,要与代码中调用者 bean 类的某引用类型属性类型同源。即要么相同,要么有 is-a 关系(子 类,或是实现类)。但这样的同源的被调用 bean 只能有一个。多于一个,容器就不知该匹配哪一个

语法如下:

<bean id="xx" class="xx" autowire="byType">
    <property name="xx" value="xx" />
</bean>

同源关系:

(1)java类中引用类型的数据类型和bean的class的值一致

(2)java类中引用类型的数据类型和bean的class的值是父子类关系

(3)java类中引用类型的数据类型和bean的class的值是接口和实现类关系 

User和Address对象

public class User 
    private String userName;
    private int age;

    //声明一个引用类型
    private Address address;
    private Address address1;

    public User() 
        System.out.println("spring会调用User类的无参构造方法创建对象");
    

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

    public void setAge(int age) 
        this.age = age;
    

    public void setAddress(Address address) 
        System.out.println("address:"+address);
        this.address = address;
    

    public void setAddress1(Address address1) 
        System.out.println("address1111:"+address1);
        this.address1 = address1;
    

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



public class Address 
    private String name;
    private String address;

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

    public void setAddress(String address) 
        this.address = address;
    

    @Override
    public String toString() 
        return "Address" +
                "name='" + name + '\\'' +
                ", address='" + address + '\\'' +
                '';
    




public class DetailAddress extends Address

spring配置文件 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">

    <!-- 引用类型自动注入:spring根据某些规则给引用类型赋值
        常用规则:byName;byType
        1、byName(按名称注入):
            Java中引用类型的属性名和spring容器(spring配置文件)中<bean>的id名称一致
            且数据类型一致,这样spring容器中的bean就能够给属性赋值

            语法:
            <bean id="xx" class="xx" autowire="byName">
                <property name="xx" value="xx" />
            </bean>
        2、byType(按类型注入):
            Java中引用类型的数据类型和spring容器(spring配置文件)的<bean>的class属性是同源关系
           同源关系:
            (1)java类中引用类型的数据类型和bean的class的值一致
            (2)java类中引用类型的数据类型和bean的class的值是父子类关系
            (3)java类中引用类型的数据类型和bean的class的值是接口和实现类关系
           语法:
           <bean id="xx" class="xx" autowire="byType">
                <property name="xx" value="xx" />
           </bean>

           注:
           (1)使用byName,属性是引用类型时,不用使用<property>标签,但是单独声明引用类型时
            其<bean>标签的id值需要和Java属性值名一致
           (2)在byType中, 在xml配置文件中声明bean只能有一个,多余一个报错
            NoUniqueBeanDefinitionException:
            No qualifying bean of type 'com.mycompany.p5referenceautobytype.Address' available:
            expected single matching bean but found 2: myAddress,mySubAddress
    -->

    <!-- (2)byType -->
    <bean id="user" class="com.mycompany.p5referenceautobytype.User" autowire="byType">
        <property name="userName" value="admin" />
        <property name="age" value="20" />
        <!--引用类型-->
<!--        <property name="address" ref="myAddress" />-->
    </bean>

    <!--声明Address对象-->
<!--    <bean id="myAddress" class="com.mycompany.p5referenceautobytype.Address">-->
<!--        <property name="name" value="家住址" />-->
<!--        <property name="address" value="江南水乡" />-->
<!--    </bean>-->

    <!--声明Address对象子类-->
    <bean id="mySubAddress" class="com.mycompany.p5referenceautobytype.DetailAddress">
        <property name="name" value="详细家住址" />
        <property name="address" value="详细江南水乡" />
    </bean>

</beans>

注:
在byType中, 在xml配置文件中声明bean只能有一个,多余一个报错

NoUniqueBeanDefinitionException: No qualifying bean of type 'com.mycompany.p5referenceautobytype.Address' available: expected single matching bean but found 2: myAddress,mySubAddress

(四)多个Spring配置文件

在实际应用里,随着应用规模的增加,系统中 Bean 数量也大量增加,导致配置文件变得非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可以将Spring 配置文件分解成多个配置文件。

包含关系的配置文件:

多个配置文件中有一个总文件,总配置文件将各其它子文件通过<import/>引入。在 Java代码中只需要使用总配置文件对容器进行初始化即可

applicationContext.xml :表示主配置文件

包含关系配置文件;包含其他的配置文件的,主配置文件一般是不定义对象

语法:

 <import resource="其他配置文件路径" /> 

classpath:类路径(class文件所在的目录) 
在spring的配置文件中要指定其他文件的位置, 需要使用classpath,告诉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">

    <!--applicationContext.xml :表示主配置文件
        包含关系配置文件;包含其他的配置文件的,主配置文件一般是不定义对象
        语法:
            <import resource="其他配置文件路径" />
            classpath:类路径(class文件所在的目录)
                在spring的配置文件中要指定其他文件的位置, 需要使用classpath,告诉spring到哪去加载读取文件
    -->

    <!-- (1)加载文件列表 -->
    <import resource="classpath:p6moreconfig/spring-user.xml" />
    <import resource="classpath:p6moreconfig/spring-address.xml" />

    <!-- (2)通配符批量加载
        在包含关系的配置文件中,可以通配符(*:表示任意字符)
        注: 主的配置文件名称不能包含在通配符的范围内(主配置文件不能定义为spring-xx.xml)
        查找文件陷入死循环,报错
        BeanDefinitionStoreException: Detected cyclic loading of file [D:\\xx\\工程模块名\\target\\classes\\p6moreconfig\\spring-total.xml] - check your import definitions!
     -->
<!--    <import resource="classpath:p6moreconfig/spring-*.xml" />-->

</beans>

User类的配置文件

<?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 id="user" class="com.mycompany.p6moreconfig.User" autowire="byType">
        <property name="userName" value="admin" />
        <property name="age" value="20" />
        <!--引用类型-->
<!--        <property name="address" ref="myAddress" />-->
    </bean>

</beans>

以上是关于Java--Spring之IoC控制反转;基于XML配置文件的DI的主要内容,如果未能解决你的问题,请参考以下文章

[转]Java Spring的Ioc控制反转Java反射原理

spring技术内幕读书笔记之IoC容器的学习

Java Spring 框架初步学习总结简单实现 IoC 和 AOP

Java Spring 两大特色

Java Spring IOC用法

大话DI依赖注入+IOC控制反转 之 定义