学习日志day48(2021-09-14)(1、Spring框架 2、Bean管理 3、IOC和DI)

学习内容:学习Spring框架(Day48)

1、Spring框架
2、Bean管理
3、IOC和DI


1、Spring框架

(1)Spring框架可以简化用户编码过程。Spring相当于一个容器,可以帮助管理项目中各种类,需要使用的时候不用自己去定义,可以调用Spring中的方法去它所管理的组件中进行查找,然后直接给你所需要的组件。Spring构成如下:
在这里插入图片描述

(2)需要的依赖,这几个依赖的版本要对应:
spring-core.jar
spring-beans.jar
spring-context.jar

2、Bean管理

(1)Bean代表项目中的Java类,要管理这些Bean,先要创建applicationContext.xml。在Maven项目的main目录下的resource目录下创建applicationContext.xml。

<?xml version="1.0" encoding="UTF-8"?>
<!--添加schema验证-->
<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">
</beans>

给applicationContext.xml文件添加<bean>节点,将类交给Spring管理

<!--通过id获取bean,一个类只能有一个id,class是类的位置-->
<bean id="UserDao" class="com.hisoft.dao.impl.UserDaoImp"/>
<!--通过name获取bean,一个类可以有多个name-->
<bean name="User,UserDaoImp" class="com.hisoft.dao.impl.UserDaoImp"/>
<!--  不加id和name可以写多个相同的bean  -->
<bean class="com.hisoft.dao.impl.UserDaoImp"/>
<bean class="com.hisoft.dao.impl.UserDaoImp"/>

(2)在测试类中获取bean

public class SpringTest {
    public static void main(String[] args) {
        //构建Spring实例,此时创建了所有bean的实例,执行所有bean实例的构造方法
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取bean的实例,根据id获取
        UserDaoImp userDao = (UserDaoImp) context.getBean("UserDao");
        //获取bean的实例,根据name获取
        UserDaoImp userDao2 = (UserDaoImp) context.getBean("UserDaoImp");
        //获取bean的实例,根据完全限定名获取,可以在完全限定名后面加 #0 来获取第1个UserDaoImp实例
        UserDaoImp userDao3 = (UserDaoImp) context.getBean("com.hisoft.dao.impl.UserDaoImp#0");
        //调用实例的方法
        userDao.save();
    }
}

(3)初始化和销毁方法
在User类中定义init()方法,并在bean中添加属性init-method=“init”,就可以在创建bean实例的时候执行init()方法。

<bean id="UserDao" class="com.hisoft.dao.impl.UserDaoImp" init-method="init"/>

在User类中定义destroy()方法,并在bean中添加属性destroy-method=“destroy”,就可以在调用close方法时,即容器关闭时执行destroy()方法。

<bean id="UserDao" class="com.hisoft.dao.impl.UserDaoImp" destroy-method="destroy"/>

(4)Bean的延迟加载
如果不想在创建Spring实例的时候创建bean实例,可以在bean中添加lazy-init=“true”(默认值是false)来延迟创建bean实例,只有在获取bean实例的时候才创建bean实例。

<bean class="com.hisoft.dao.impl.UserDaoImp" lazy-init="true"/>

(5)单例和多例
增加scope属性,将bean设置为单例(默认)或者多例的

<!--单例-->
<bean class="com.hisoft.dao.impl.UserDaoImp" scope="singleton"/>
<!--多例-->
<bean class="com.hisoft.dao.impl.UserDaoImp" scope="prototype"/>

3、IOC和DI

(1)IoC(Inversion of Control,控制反转):Spring的核心,对于Spring框架来说,就是由Spring来负责控制对象的生命周期和对象间的关系。在对象A中要使用对象B时,称A依赖于B,B就是A的依赖对象。平常我们会使用new object()这样的方式在对象A中将依赖对象B创建出来,这样两个对象就产生了耦合。但是在Spring中,创建依赖对象B是由Spring完成的,Spring创建好B对象,然后存储到Spring容器里面,当A对象需要使用B对象时,Spring就从容器中取出,然后交给A对象使用。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。

DI(Dependency Injection,依赖注入):Spring在系统运行中,动态的向某个对象提供它所需要的其他对象,这就是通过依赖注入实现的。IoC和DI从不同的角度描述了Spring容器创建对象并提供对象的过程。依赖注入有set注入、构造方法注入、自动注入三种。

(2)set注入
UserServiceImpl类中需要用到UserDao对象和一些全局变量,这些对象和变量值可以通过set注入的方式来获取。

public class UserServiceImpl {
    //userDao是一个接口对象,面向接口编程:解耦(降低耦合度)    
    //例如连接数据库有oracleDao和mysqlDao两种对象,使用一个userDao接口对象就可以实现接收不同的数据库对象
    private UserDao userDao;
    
    public String name;
    public Integer age;
    public List<String> stringList;
    public Map<String,Object> map;
    public Properties properties;

    //创建set方法
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

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

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setStringList(List<String> stringList) {
        this.stringList = stringList;
    }

    public void setMap(Map<String, Object> map) {
        this.map = map;
    }

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

在applicationContext.xml文件中添加<property>节点实现注入,将UserDaoImp对象注入UserServiceImpl对象中。

<bean name="userDao" class="com.hisoft.dao.impl.UserDaoImp"/>
<bean id="userService" class="com.hisoft.service.UserServiceImpl">
    <!-- name表示UserServiceImpl类中的set方法的名称,ref表示Spring容器中bean的id或name -->
    <property name="userDao" ref="userDao"/>
</bean>

其它配置方式

<bean name="userDao" class="com.hisoft.dao.impl.UserDaoImp"/>
<bean id="userService" class="com.hisoft.service.UserServiceImpl"> 
    <property name="userDao"> 
        <ref bean="userDao"/> 
    </property> 
</bean>
<bean id="userService" class="com.hisoft.service.UserServiceImpl"> 
    <property name="userDao"> 
        <!--此时这个bean的作用域只在property中-->
        <bean class="com.hisoft.dao.impl.UserDaoImp"/> 
    </property> 
</bean>

将变量的值注入UserServiceImpl对象中

<bean id="userService" class="com.hisoft.service.UserServiceImpl">
    <!--注入String和int型-->
    <property name="name" value="Tom"/>
    <property name="age" value="12"/>
    <!--注入List集合-->
    <property name="stringList">
        <list>
            <value>Jerry</value>
            <value>Jack</value>
            <value>Jone</value>
        </list>
    </property>
    <!--注入Map集合-->
    <property name="map">
        <map>
            <entry key="j">
                <value>J</value>
            </entry>
            <entry key="k">
                <value>K</value>
            </entry>
        </map>
    </property>
    <!--注入properties对象-->
    <property name="properties">
        <props>
            <prop key="r">R</prop>
        </props>
    </property>
</bean>

(3)构造方法注入
BookServiceImpl类中创建一个构造方法,参数是需要用到的BookDao对象和一些变量。

public class BookServiceImpl {

    private BookDao bookDao;

    public BookServiceImpl(BookDao bookDao, String name, String address){
        System.out.println(name);
        System.out.println(address);
        this.bookDao = bookDao;
    }
}

在applicationContext.xml文件中添加<constructor-arg>节点实现构造方法注入

<bean id="bookDao" class="com.hisoft.dao.impl.BookDaoImpl"></bean>
<bean id="bookService" class="com.hisoft.service.BookServiceImpl">
    <!--name表示BookServiceImpl对象中构造方法的参数名称,value表示要注入的参数值,ref表示Spring容器中bean的id或name-->
    <constructor-arg name="address" value="beijing"/>
    <constructor-arg name="name" value="Rose"/>
    <constructor-arg name="bookDao" ref="bookDao"/>
</bean>

其它配置方式

<!--type表示注入的数据类型,根据数据类型匹配,无法保证顺序正确-->
<constructor-arg type="com.hisoft.dao.BookDao" ref="bookDao"/>
<constructor-arg type="java.lang.String" value="Beijing"/>
<constructor-arg type="java.lang.String" value="Jack"/>
<!--index表示注入的第几个参数-->
<constructor-arg index="0" ref = "bookDao"/>
<constructor-arg index="2" value="beijing"/>
<constructor-arg index="1" value="jack" />
<!--只设置注入的value和ref时会根据数据类型自动匹配,无法保证顺序正确-->
<constructor-arg value="beijing"></constructor-arg>
<constructor-arg value="tom"></constructor-arg>
<constructor-arg ref="bookDao"/>
<!--注入的参数是一个集合时-->
<constructor-arg>
    <list>
        <value>Jack</value>
        <value>Rose</value>
    </list>
</constructor-arg>

(4)实际开发中经常使用的是set注入方法
使用构造方法注入的理由:
• 构造方法注入使用强依赖规定,如果不给足够的参数,对象则无法创建。
• 由于Bean 的依赖都通过构造方法设置了,那么就不用写更多的 set 方法,有助于减少代码量。
使用 set 注入的理由:
• 如果Bean有很多的依赖,那么构造方法的参数列表会变的很长。
• 如果一个对象有多种构造方法,构造方法会造成代码量增加。
• 如果构造方法中有两个以上的参数类型相同,那么将很难确定参数的用途。

(5)自动注入
1.需要注入的对象中有set方法时

public class NewsServiceImpl {
    private NewsDao newsDao;
    //创建set方法
    public void setNewsDao(NewsDao newsDao) {
        this.newsDao = newsDao;
    }
}

applicationContext.xml文件,在要注入的对象的bean中添加autowire属性

<bean id = "newsDao" class="com.hisoft.dao.impl.NewsDaoImpl" />
<bean id = "newsDao2" class="com.hisoft.dao.impl.NewsDaoImpl2" />
<!--此时autowire的属性不能是byType,因为有两个相同类型的bean,匹配的类型只有一个时才能使用byType-->
<!--byName查找的是NewsServiceImpl类中的set方法的名字进行匹配-->
<bean id = "newsService" class="com.hisoft.service.NewsServiceImpl"  autowire="byName"/>

2.需要注入的对象中有构造方法时

public class NewsServiceImpl {
    private NewsDao newsDao;

    public NewsServiceImpl(NewsDao newsDao){
        this.newsDao = newsDao;
    }
}
<bean id = "newsDao" class="com.hisoft.dao.impl.NewsDaoImpl" />
<bean id = "newsDao2" class="com.hisoft.dao.impl.NewsDaoImpl2" />
<!--与byType的方式类似,不同之处在于它应用于构造器参数-->
<bean id = "newsService" class="com.hisoft.service.NewsServiceImpl"  autowire="constructor"/>

autowire的值:
• no 默认值,不进行自动注入
• byName 根据需要注入的属性名在容器内寻找名称相同的Bean,如果找到就注入,找不到就不注入
• byType 根据需要注入的属性类型在容器找类型相同的Bean,如果找到就注入,找不到就不注入,如果找到多个 类型相同的Bean,则抛出异常
• constructor 与byType的方式类似,不同之处在于它应用于构造器参数。如果在容器中没有找到与构造器参数类型一致的bean,那么将会抛出异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值