Spring IOC 手动注入

Spring IOC 注入

主动实例化

1.设置配置文件

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="accountService" class="com.xxxx.service.AccountService"/>
    
</beans>

2.编写Bean对象
AccountDao.java

package com.xxxx.dao;

public class AccountDao {
    
    

    public void test(){
    
    
        System.out.println("AccountDao...");
    }
}

AccountService.java

package com.xxxx.service;

import com.xxxx.dao.AccountDao;

public class AccountService {
    
    
    //主动实例化
    AccountDao accountDao = new AccountDao();

    public void test(){
    
    
        System.out.println("AccountService...");
        accountDao.test();
    }
}

3.获取实例化对象

package com.xxxx;



import com.xxxx.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    
    
    public static void main(String[] args) {
    
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");

        AccountService accountService = (AccountService) ac.getBean("accountService");

        accountService.test();

    }
}

4.运行结果

AccountService...
AccountDao...

Spring IOC 手动注入(装配)

set方法注入

属性字段需要提供set⽅法

业务对象 JavaBean

1.dao层的bean对象

package com.xxxx.dao;

public class AccountDao {
    
    

    public void test(){
    
    
        System.out.println("AccountDao...");
    }
}

2.属性字段提供set方法

package com.xxxx.service;

import com.xxxx.dao.AccountDao;

public class AccountService {
    
    

    //JavaBean对象 手动注入 set方法注入
    private AccountDao accountDao;
    //提供set方法
    public void setAccountDao(AccountDao accountDao) {
    
    
        this.accountDao = accountDao;
    }

    public void test(){
    
    
        System.out.println("AccountService...");

        accountDao.test();
    }
}

3.配置文件的bean标签设置property标签

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--set方法注入,需要提供set方法-->
    <!--通过property属性设置set方法-->
    <!--name:字段名    ref:对应的bean标签的is属性值-->
    <bean id="accountDao" class="com.xxxx.dao.AccountDao"/>
    <bean id="accountService" class="com.xxxx.service.AccountService">
    <!--set方法注入:JavaBean对象-->
        <property name="accountDao" ref="accountDao"/>
    </bean>

</beans>

4.获取实例化对象

package com.xxxx;



import com.xxxx.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    
    
    public static void main(String[] args) {
    
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");

        AccountService accountService = (AccountService) ac.getBean("accountService");

        accountService.test();

    }
}

5.运行结果

AccountService...
AccountDao...

常用对象和基本类型

1.属性字段提供set方法

package com.xxxx.service;

public class AccountService {
    
    

    //字符串类型
    private String host;
    //提供set方法
    public void setHost(String host) {
    
    
        this.host = host;
    }

    //基本类型
    private Integer port;
    //提供set方法
    public void setPort(Integer port) {
    
    
        this.port = port;
    }

    public void test(){
    
    
        System.out.println("AccountService...");
        System.out.println(host);
        System.out.println(port);
    }
}

2.配置文件的bean标签设置property标签

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--set方法注入,需要提供set方法-->
    <!--通过property属性设置set方法-->
    <!--name:bean对象中属性字段名    value:具体的值(基本类型、常用对象|日期 集合)-->
    <bean id="accountService" class="com.xxxx.service.AccountService">
        <!--字符串类型-->
        <property name="host" value="localhost"/>
        <!--基本类型-->
        <property name="port" value="8080"/>
    </bean>

</beans>

3.获取实例化对象

package com.xxxx;



import com.xxxx.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    
    
    public static void main(String[] args) {
    
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");

        AccountService accountService = (AccountService) ac.getBean("accountService");

        accountService.test();

    }
}

4.运行结果

AccountService...
localhost
8080

集合类型和属性对象

1.属性字段提供set方法

package com.xxxx.service;

import com.xxxx.dao.AccountDao;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class AccountService {
    
    

    //List集合
    private List<String> list;

    public void setList(List<String> list) {
    
    
        this.list = list;
    }
    //list集合输出
    public void printList(){
    
    
        list.forEach(v -> System.out.println(v));
    }


    //Set集合
    private Set<String> set;

    public void setSet(Set<String> set) {
    
    
        this.set = set;
    }
    // Set集合输出
    public void printSet() {
    
    
        set.forEach(s -> System.out.println(s));
    }


    //Map
    private Map<String,Object> map;

    public void setMap(Map<String, Object> map) {
    
    
        this.map = map;
    }
    // Map输出
    public void printMap() {
    
    
        map.forEach((k,v) -> System.out.println(k + "," + v));
    }


    //Properties
    private Properties properties;

    public void setProperties(Properties properties) {
    
    
        this.properties = properties;
    }

    // Properties输出
    public void printProperties(){
    
    
        properties.forEach((k,v) -> System.out.println(k + ","+ v ));
    }



    public void test(){
    
    
        System.out.println("AccountService...");
        // List集合
        printList();
        // Set集合
        printSet();
        // Map
        printMap();
        // Properties
        printProperties();
    }

}

2.配置文件的bean标签设置property标签

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--set方法注入,需要提供set方法-->
    <!--通过property属性设置set方法-->
    <!--name:bean对象中属性字段名    value:具体的值(基本类型、常用对象|日期 集合)-->
    
    <bean id="accountService" class="com.xxxx.service.AccountService">

        <!--List集合注入-->
        <property name="list">
            <list>
                <value>北京</value>
                <value>上海</value>
                <value>深圳</value>
            </list>
        </property>

        <!--Set集合注⼊-->
        <property name="set">
            <set>
                <value>上海SH</value>
                <value>北京BJ</value>
                <value>杭州HZ</value>
            </set>
        </property>


        <!--Map注⼊-->
        <property name="map">
            <map>
                <entry>
                    <key><value>周杰伦</value></key>
                    <value>我是如此相信</value>
                </entry>
                <entry>
                    <key><value>林俊杰</value></key>
                    <value>可惜没如果</value>
                </entry>
                <entry>
                    <key><value>陈奕迅</value></key>
                    <value>⼗年</value>
                </entry>
            </map>
        </property>


        <!--Properties注⼊-->
        <property name="properties">
            <props>
                <prop key="上海">东⽅明珠</prop>
                <prop key="北京">天安⻔</prop>
                <prop key="杭州">⻄湖</prop>
            </props>
        </property>

    </bean>

</beans>

3.获取实例化对象

package com.xxxx;



import com.xxxx.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    
    
    public static void main(String[] args) {
    
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");

        AccountService accountService = (AccountService) ac.getBean("accountService");

        accountService.test();

    }
}

4.运行结果

AccountService...
北京
上海
深圳
上海SH
北京BJ
杭州HZ
周杰伦,我是如此相信
林俊杰,可惜没如果
陈奕迅,⼗年
上海,东⽅明珠
北京,天安⻔
杭州,⻄湖

构造器注入

需要提供带参构造器,构造器有几个参数就需要设置几个constructor-arg标签
通过constructor-arg标签设置构造器的形参(name 形参名 )

单个Bean对象作为参数

1.JavaBean对象

package com.xxxx.service;

import com.xxxx.dao.TypeDao;

/**
 * 构造器注入
 */
public class TypeService {
    
    

    private TypeDao typeDao;

    //提供带参构造
    public TypeService(TypeDao typeDao) {
    
    
        this.typeDao = typeDao;
    }

    public void test(){
    
    
        System.out.println("TypeService...");
        typeDao.test();
    }
}

2.设置配置文件

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--构造器注入-->
    <bean id="typeDao" class="com.xxxx.dao.TypeDao"/>
    <bean id="typeService" class="com.xxxx.service.TypeService">
        <constructor-arg name="typeDao" ref="typeDao"/>
    </bean>
    
</beans>

3.获取实例化对象

package com.xxxx;

import com.xxxx.service.TypeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    
    
    public static void main(String[] args) {
    
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");

        TypeService typeService = (TypeService) ac.getBean("typeService");

        typeService.test();

    }
}

4.运行结果

TypeService...
TypeDao...

多个Bean对象作为参数

1.JavaBean对象

package com.xxxx.service;

import com.xxxx.dao.TypeDao;
import com.xxxx.dao.UserDao;

/**
 * 构造器注入
 */
public class TypeService {
    
    

    private TypeDao typeDao;
    private UserDao userDao;

    //提供带参构造
    public TypeService(TypeDao typeDao, UserDao userDao) {
    
    
        this.typeDao = typeDao;
        this.userDao = userDao;
    }

    public void test(){
    
    
        System.out.println("TypeService...");
        typeDao.test();
        userDao.test();
    }
}

2.设置配置文件

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--构造器注入-->
    <bean id="typeDao" class="com.xxxx.dao.TypeDao"/>
    <bean id="userDao" class="com.xxxx.dao.UserDao"/>
    <bean id="typeService" class="com.xxxx.service.TypeService">
        <constructor-arg name="typeDao" ref="typeDao"/>
        <constructor-arg name="userDao" ref="userDao"/>
    </bean>

</beans>

3.获取实例化对象

package com.xxxx;

import com.xxxx.service.TypeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    
    
    public static void main(String[] args) {
    
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");

        TypeService typeService = (TypeService) ac.getBean("typeService");

        typeService.test();

    }
}

4.运行结果

TypeService...
TypeDao...
UserDao...

Bean对象和常用对象作为参数

package com.xxxx.service;

import com.xxxx.dao.TypeDao;
import com.xxxx.dao.UserDao;

/**
 * 构造器注入
 */
public class TypeService {
    
    

    private TypeDao typeDao;
    private UserDao userDao;
    private String name;

    public TypeService(TypeDao typeDao, UserDao userDao, String name) {
    
    
        this.typeDao = typeDao;
        this.userDao = userDao;
        this.name = name;
    }

    public void test(){
    
    
        System.out.println("TypeService...");
        typeDao.test();
        userDao.test();
        System.out.println(name);
    }
}

设置配置文件

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--构造器注入-->
    <bean id="typeDao" class="com.xxxx.dao.TypeDao"/>
    <bean id="userDao" class="com.xxxx.dao.UserDao"/>
    <bean id="typeService" class="com.xxxx.service.TypeService">
        <constructor-arg name="typeDao" ref="typeDao"/>
        <constructor-arg name="userDao" ref="userDao" />
        <constructor-arg name="name" value="admin" index="2"/>
        <!--index:构造器中参数的下标,从0开始-->
    </bean>

</beans>

获取实例化对象

package com.xxxx;

import com.xxxx.service.TypeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    
    
    public static void main(String[] args) {
    
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");

        TypeService typeService = (TypeService) ac.getBean("typeService");

        typeService.test();

    }
}

运行结果

TypeService...
TypeDao...
UserDao...
admin

循环依赖问题

循环问题产生的原因:
Bean通过构造器注入,之间彼此相互依赖对方导致bean无法实例化。

问题展示:

A.java

package com.xxxx.service;

import com.xxxx.dao.B;

public class A {
    
    

    private B b;

    public A(B b) {
    
    
        this.b = b;
    }

    public void test(){
    
    
        System.out.println("A test ...");
        b.test();
    }
}

B.java

package com.xxxx.dao;

import com.xxxx.service.A;

public class B {
    
    
    private A a;

    public B(A a) {
    
    
        this.a = a;
    }

    public void test(){
    
    
        System.out.println("B test ...");
        a.test();
    }
}

设置配置文件

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="a" class="com.xxxx.service.A">
        <constructor-arg name="b" ref="b"/>
    </bean>
    <bean id="b" class="com.xxxx.dao.B">
        <constructor-arg name="a" ref="a"/>
    </bean>
    
</beans>

测试

package com.xxxx;

import com.xxxx.service.TypeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Starter {
    
    
    public static void main(String[] args) {
    
    

        ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
    }
}

解决循环依赖

如何解决:将构造器注入改为set方法注入

1.将构造方法换成set方法

package com.xxxx.service;

import com.xxxx.dao.B;

public class A {
    
    

    private B b;

//    public A(B b) {
    
    
//        this.b = b;
//    }


    public void setB(B b) {
    
    
        this.b = b;
    }

    public void test(){
    
    
        System.out.println("A test ...");
        b.test();
    }
}

package com.xxxx.dao;

import com.xxxx.service.A;

public class B {
    
    
    private A a;

//    public B(A a) {
    
    
//        this.a = a;
//    }


    public void setA(A a) {
    
    
        this.a = a;
    }

    public void test(){
    
    
        System.out.println("B test ...");
        a.test();
    }
}

2.修改标签

<?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
       https://www.springframework.org/schema/beans/spring-beans.xsd">

<!--    <bean id="a" class="com.xxxx.service.A">-->
<!--        <constructor-arg name="b" ref="b"/>-->
<!--    </bean>-->
<!--    <bean id="b" class="com.xxxx.dao.B">-->
<!--        <constructor-arg name="a" ref="a"/>-->
<!--    </bean>-->


    <bean id="a" class="com.xxxx.service.A">
        <property name="b" ref="b"/>
    </bean>
    <bean id="b" class="com.xxxx.dao.B">
        <property name="a" ref="a"/>
    </bean>

</beans>

静态工厂注入

1.定义静态工厂类

package com.xxxx.factory;


import com.xxxx.dao.UserDao;


/**
 * 静态工厂类
 *      1.定义静态工厂类
 *      2.定义静态方法,并返回需要被实例化的Bean对象
 */
public class StaticFactory {
    
    
    /**
     * 静态方法
     */
    public static UserDao createUserDao(){
    
    
        System.out.println("静态工厂实例化...");
        return new UserDao();
    }

}

2.java代码

package com.xxxx.service;

import com.xxxx.dao.UserDao;

public class UserService {
    
    


    private UserDao userDao;

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

    public void test(){
    
    
        System.out.println("UserService...");
    }
}

xml配置

    <bean id="userService" class="com.xxxx.service.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>

    <bean id="userDao" class="com.xxxx.factory.StaticFactory" factory-method="createUserDao"/>

实例化工厂注入

1.定义工厂类

package com.xxxx.factory;

import com.xxxx.dao.UserDao;

public class InstanceFactory {
    
    
    /**
     * 定义方法,返回实例化对象
     */
    public UserDao createUserDao(){
    
    
        System.out.println("实例化工厂实例化...");
        return new UserDao();
    }
}

2.java代码

package com.xxxx.service;

import com.xxxx.dao.UserDao;

public class UserService {
    
    


    private UserDao userDao;

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

    public void test(){
    
    
        System.out.println("UserService...");
    }
}

3.xml配置

    <bean id="userService" class="com.xxxx.service.UserService">
        <property name="userDao" ref="userDao"/>
    </bean>
    <!--实例化工厂注入:也是借助set方法注入,只是被注入的bean对象的实力护士是通过工厂实例化的-->
    <bean id="instanceFactory" class="com.xxxx.factory.InstanceFactory"/>
    <bean id="userDao" factory-bean="instanceFactory" factory-method="createUserDao"/>

注入方式的选择

开发项目中set方式注入首选

	使⽤构造注入可以在构建对象的同时⼀并完成依赖关系的建⽴,对象⼀建⽴则所有的⼀切也就准备好了,但如果要建⽴的对象关系很多,
使⽤构造器注⼊会在构建函数上留下⼀⻓串的参数,且不易记忆,这时使⽤Set注⼊会是个不错的选择。

  使⽤Set注⼊可以有明确的名称,可以了解注⼊的对象会是什么,像setXXX()这样的名称会⽐记忆Constructor上某个参数的位置代表某个对象更好。

p名称空间的使用

spring2.5以后,为了简化setter方法属性注入,引用p名称空间的概念,可以将 property 子元素简化为 bean 元素属性配置。

1.属性字段提供 set 方法

public class UserService {
    
    
	 // 业务对象UserDao set注⼊(提供set⽅法)
	 private UserDao userDao;
	 public void setUserDao(UserDao userDao) {
    
    
		 this.userDao = userDao;
	 }
	 
	 // 常⽤对象String set注⼊(提供set⽅法)
	 private String host;
	 public void setHost(String host) {
    
    
		 this.host = host;
	 }
}

2.在配置文件spring.xml引入p名称空间

xmlns:p="http://www.springframework.org/schema/p"
 <?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"
		xsi:schemaLocation="http://www.springframework.org/schema/beans
		https://www.springframework.org/schema/beans/spring-beans.xsd">

 <bean id="userDao" class="com.xxxx.dao.UserDao"></bean>
 <!--
	p:属性名:="xxx" 引⼊常量值
	p:属性名-ref:="xxx" 引⼊其他Bean对象的id属性值
 -->
 <bean id="userService" class="com.xxxx.service.UserService"
	p:userDao-ref="userDao"
	p:host="127.0.0.1" />
 </beans>

猜你喜欢

转载自blog.csdn.net/lln1540295459/article/details/121100485