Spring01--Spring Framework

1.Spring入门

官网:Spring | Home

Spring全家桶:

1.1.Spring Framework系统架构

  Spring Framework是Spring生态圈最基础的项目,是其它项目的根基。

如上图所示:

Core Container:核心容器

AOP:面向切面编程----Aspects:AOP思想的实现

Data Access/Integration:数据访问/集成

      Transactions:事务

Web:Web开发

Test:单元测试与集成测试

1.2.IOC--控制反转

1.2.1IOC

  IoC(Inversion of Control):对象的创建由程序转移到外部,转换为外部提供的对象,这种思想被称为控制反转(对象创建控制权发生变化)

 Spring技术对IOC思想进行了实现。Spring提供了一个容器,称为IoC容器

 IoC容器负责对象的创建、初始化等一系列工作,被创建或被管理的对象在Ioc容器中统称为Bean.

  1.2.2DI 依赖注入

Dependency Injection(简写为DI) -----依赖注入:在容器中建立Bean与Bean之间的依赖关系的整个过程,称为依赖注入。

1.2.3Ioc jar包介绍

Spring-core:Spring的核心工具包,spring的其它包都要用到该jar中的类

Spring-beans:包含配置文件,bean的创建等,所有jar包都需要用到

Spring-context:在上面两个jar完成基础IOC功能上提供扩展服务,此外还提供许多企业级服务的支持,有邮件服务、任务调度、JNDI定位,EJB集成、远程访问、缓存以及多种视图层框架的支持。

Spring-expression:Spring表达式语言,spel表达式,SpEL支持标准数学运算符,关系运算符,逻辑运算符,条件运算符,集合和正则表达式等${url}

Spring-context-support:Spring context的扩展支持,用于MVC方面,比如支持freemarker等模板引擎

1.3Ioc案例(基于XML)

1.创建maven项目:

2.在Pom.xml里面导入依赖:

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <!--Spring上下文,提供了IOC容器等最基础的功能-->
                <artifactId>spring-context</artifactId>
                <version>6.0.9</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <!--Spring上下文,提供了IOC容器等最基础的功能-->
            <artifactId>spring-context</artifactId>
        </dependency>
    </dependencies>

3.建立代码分层
 

BookDao,BookDaoImpl,BookService,BookServiceImpl相关代码如下:

public interface BookDao {
    void save();
}


public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("BookDaoImpl里的save()执行了。。。。。。");
    }
}


public interface BookService {
    void save();
}


public class BookServiceImpl implements BookService {

    private BookDao bookDao=new BookDaoImpl();
    @Override
    public void save() {
        System.out.println("Book ServiceImpl Save方法执行了。。。。。。。。。。");
        bookDao.save();
    }
}




4.右键resources目录下创建一个新的配置文件

5.配置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">
    <!--id(bean名字)必须唯一-->
    <!--class:映射类路径-->
    <bean id="bookDao" class="com.hb.mapper.impl.BookDaoImpl" ></bean>
    <bean id="bookService" class="com.hb.service.impl.BookServiceImpl"></bean>
</beans>

6.对Dao进行测试:

package com.hb;

import com.hb.mapper.BookDao;
import com.hb.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {
        //获取Ioc容器
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取Bean
        System.out.println("----------Dao--------------");
       BookDao bookDao=(BookDao) ctx.getBean("bookDao");
       bookDao.save();

        System.out.println("--------------Service--------------");
        BookService service=(BookService) ctx.getBean("bookService");
        service.save();

    }
}

运行结果:

1.4DI案例(基于XML)

基于上一个案例

1.提供BookServiceImpl中的属性bookDao的setter

public class BookServiceImpl implements BookService {

    private BookDao bookDao;
    @Override
    public void save() {
        System.out.println("Book ServiceImpl Save方法执行了。。。。。。。。。。");
        bookDao.save();
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

2.在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">
    <!--id(bean名字)必须唯一-->
    <!--class:映射类路径-->
    <bean id="bookDao1" class="com.hb.mapper.impl.BookDaoImpl" ></bean>
    <bean id="bookService" class="com.hb.service.impl.BookServiceImpl">
        <!--配置Service与Dao的关系-->
        <!--name:属性名
             ref:参考Bean名-->
             <property name="bookDao" ref="bookDao1"/>
    </bean>
</beans>

运行效果:

1.5bean基于XML配置

1.5.1基本配置

id:bean的id,使用容器可以通过id值获取对应的bean,在一个容器中id唯一

class:bean的类型,即配置bean的类路径名

name:bean的别名,多个别名之间可以用逗号/空格分割

1.5.2bean作用范围配置

scope:控制bean作用范围,默认为singleton(单例),可以改为prototype(非单例)

适合造单例的bean(适合交给容器管理的bean):

  表现层对象

  业务层对象

  数据层对象

  工具对象

不适合造单例的bean(不适合交给容器管理的bean):

  封装实体的域对象

1.6bean的四种实例化形式

1.6.1.基于构造方法实例化(默认,常用)

调用无参构造方法(不管构造方法私有还是公有,因为底层使用反射)

1.6.2.使用静态工厂

创建静态工厂示例代码如下(注意方法必须为静态方法):

这里利用BookDaoFactory对于BookDao进行管理,所以需要修改配置(注意:class配置的是工厂类名,factory-method配置工厂类中的静态方法):

测试相关代码段如下:

  //获取Ioc容器
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取Bean
        System.out.println("----------Mapper--------------");
       BookDao bookDao=(BookDao) ctx.getBean("bookMapper");
       bookDao.save();

运行结果:

  该方式比较灵活,可以在工厂类中做其它配置(实际上是个代理)

1.6.3使用实例工厂

创建实例工厂(注意:此时不再是静态方法):

public class BookDaoFactory2 {
    public BookDao getBookDao(){
        return new BookDaoImpl();
    }
}

修改XML配置:

测试相关代码如下:

1.6.4.使用FactoryBean实例化

本方式是实例工厂的延伸,因为第三种的缺点是在不必要的情况下多实例化了一个工厂类,而使用FactoryBean可以解决这个问题,FactoryBean类定义如下(注意:需要实现Factory接口并重写创建Bean实例和Bean类型的方法):

package com.hb.factory;

import com.hb.mapper.BookDao;
import com.hb.mapper.impl.BookDaoImpl;
import org.springframework.beans.factory.FactoryBean;

public class BookDaoFactoryBean implements FactoryBean<BookDao> {
    /**
     * 代替原始实例工厂中创建对象的方法(即BookDaoFactory2中的getBookDao())
     * */
    @Override
    public BookDao getObject() throws Exception {
        return new BookDaoImpl();
    }

    @Override
    public Class<?> getObjectType() {
        return BookDao.class;
    }
}

然后,需要修改XML文件里有关Bean的配置如下:

测试结果如下:

可以看到,Bean被实例化了,基于以上优点,这种方式在框架整合时用得很多。

同时如果,需要用此种方式指定Bean作用范围,这需要在FactoryBean重写isSingleton()方法,返回true代表单例,false代表非单例。

1.7Bean的生命周期

bean在初始化的过程中经历了如下阶段:

初始化容器

   1.创建对象(内存分配---new)                                                

   2.执行构造方法                                                                         

   3.执行属性注入(set操作)

   4.执行bean初始化方法

使用bean:

  1.在Bean中执行相关自定义业务操作

关闭/销毁容器

  1.执行Bean方法

1.7.1自定义周期函数控制生命周期(基于XML)

Bean生命周期中比较重要的两个是Bean实例化前和Bean销毁前的两个时期,相关代码如下:

import com.hb.mapper.BookDao;

public class BookDaoImpl implements BookDao {
    @Override
    public void save() {
        System.out.println("BookDaoImpl里的save()执行了。。。。。。");
    }
    //表示Bean初始化对应的操作
    public void init(){
        System.out.println("init...加载连接!");
    }
    //表示Bean销毁前的操作
    public void destroy(){
        System.out.println("destroy...关闭连接!");
    }
}

以上代码中init()和destory()为自定义方法,同时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">
    <!--id(bean名字)必须唯一-->
    <!--class:映射类路径-->
    <bean id="bookDao1" name="bookDaoImpl bookMapper" class="com.hb.mapper.impl.BookDaoImpl"   init-method="init" destroy-method="destroy"></bean>
  <!--  <bean id="bookDaoFactory2" class="com.hb.factory.BookDaoFactory2"></bean>
    <bean id="bookMapper" factory-bean="bookDaoFactory2" factory-method="getBookDao"></bean>-->
    <bean id="bookService" class="com.hb.service.impl.BookServiceImpl">
        <!--配置Service与Dao的关系-->
        <!--name:属性名
             ref:参考Bean名-->
             <property name="bookDao" ref="bookMapper"/>
    </bean>

</beans>

同时,需要注意,Bean必须设置为单例。

测试代码如下:

import com.hb.mapper.BookDao;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppLifeCircle {
    public static void main(String[] args) {
        //获取Ioc容器
        ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");

        //获取Bean
        System.out.println("----------Mapper--------------");
        BookDao bookDao=(BookDao) ctx.getBean("bookMapper");
        bookDao.save();
        /**
         * 注册关闭钩子
         * */
        ctx.registerShutdownHook();
       /**
        * 暴力关闭
        * */
       //ctx.close();
    }
}

在以上代码中,容器关闭前触发Bean的销毁,执行close()和registerShutdownHook()都会关闭容器(ctx对象),进而将Bean销毁。

两者的运行结果都是差不多的。(如下)

两者的不同点在于前者为暴力关闭容器,直接关闭;后者为设置关闭钩子,,放在任何时间都可以(如下)

1.7.2使用接口定义周期函数控制Bean生命周期

上述过程需要在XML文件里面对生命周期函数进行配置,比较麻烦,可以使用接口的方式简化配置:这需要让Bean实现InitializingBean, DisposableBean两个接口,前者定义初始化前的生命周期过程,后者定义了销毁前的生命周期过程,然后重写两个接口的方法,如下:

import com.hb.mapper.BookDao;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class BookDaoImpl implements BookDao , InitializingBean, DisposableBean {
    @Override
    public void save() {
        System.out.println("BookDaoImpl里的save()执行了。。。。。。");
    }

    //表示Bean销毁前的操作
    @Override
    public void destroy() throws Exception {
        System.out.println("destroy...关闭连接!");
    }
    //表示Bean初始化对应的操作
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("init...加载连接!");
    }




}

此时,XML文件不许要额外配置,应为已经遵循了Spring的相关规范。如下:

运行结果如下:

2依赖注入

2.1setter注入

使用setter注入引用数据类型的例子在前面已经列举过了,即使用ref属性配置;那么如何传基本数据类型和String类型的值呢?这时候就需要使用value来进行配置了。

示例代码如下:

public class BookDaoImpl implements BookDao  {
    //连接数
    private int connectionNum;
    //数据库名称
    private String databaseName;

    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }

    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }

    @Override
    public void save() {
        System.out.println("BookDaoImpl里的save()执行了。。。。。。");
        System.out.println("连接数:"+connectionNum+"     数据库名称:"+databaseName);
    }

}

BookDao下有两个属性,一个表示连接数,一个表示数据库名,分别为int和String类型,并定义了相关的setter方便在依赖注入的时候传值。

然后,需要在XML文件中对两个属性进行加载配置,如下:

配置后,测试结果如下:

我们可以看到,为属性传值成功。

2.2构造器注入

标准书写构造器注入代码的耦合度比较高。过程如下:

将以上的BookDaoImpl加上有参构造方法,如下;

import java.util.Date;

public class BookDaoImpl implements BookDao  {
    //连接数
    private int connectionNum;
    //数据库名称
    private String databaseName;
    public BookDaoImpl(){
        System.out.println(new Date() +":执行了无参构造方法");
    }

    private BookDaoImpl( int connectionNum,String databaseName){
        this.databaseName=databaseName;
        this.connectionNum=connectionNum;
        System.out.println(new Date() +":执行了有参构造方法");
    }
    @Override
    public void save() {
        System.out.println("BookDaoImpl里的save()执行了。。。。。。");
        System.out.println("连接数:"+connectionNum+"     数据库名称:"+databaseName);
    }






}

然后在XML中修改配置如下(byName):

<?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">
    <!--id(bean名字)必须唯一-->
    <!--class:映射类路径-->
    <bean id="bookDao1" name="bookDaoImpl bookMapper" class="com.hb.mapper.impl.BookDaoImpl">
       <constructor-arg name="connectionNum" value="10"/>
        <constructor-arg name="databaseName" value="mysql"/>
    </bean>
  <!--  <bean id="bookDaoFactory2" class="com.hb.factory.BookDaoFactory2"></bean>
    <bean id="bookMapper" factory-bean="bookDaoFactory2" factory-method="getBookDao"></bean>-->
    <bean id="bookService" class="com.hb.service.impl.BookServiceImpl">
        <!--配置Service与Dao的关系-->
        <!--name:属性名
             ref:参考Bean名-->
             <property name="bookDao" ref="bookMapper"/>
    </bean>

</beans>

测试结果如下:

同时也可已通过构造函数属性类型进行参数注入(byType),这样可以解决形参名称的问题,与形参名不耦合了,这样形参名无论如何改动,xml配置里面的东西都不会改动,修改XML配置如下:

2.3自动装配

Ioc容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程(自动装配用于引用类型的依赖注入,不能对简单类型进行操作;自动装配的优先级低于setter注入和构造器注入,同时出现会导致自动装配配置失效)。自动装配的方式有以下四种:

1.按类型(常用):通过属性的类型查找JavaBean依赖的对象并为其注入。使用Seter方法为其注入。

2.按名称:通过属性的名字的方式查找JavaBean依赖的对象并为其注入,使用Seter方法为其注入。

3.按构造方法:byType一样,也是通过类型查找依赖对象。与byType的区别在于它不是使用Seter方法注入,而是使用构造方法注入

4.不启用:即不启用自动装配。Autowire默认的值。

2.3.1ByType

测试:

//BookServiceImpl
public class BookServiceImpl implements BookService {

    private BookDao bookDao;
    @Override
    public void save() {
        System.out.println("Book ServiceImpl Save方法执行了。。。。。。。。。。");
        bookDao.save();
    }

    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}
//BookDaoImpl
public class BookDaoImpl implements BookDao  {
    //连接数
    private int connectionNum;
    //数据库名称
    private String databaseName;
    public BookDaoImpl(){
        System.out.println(new Date() +":执行了无参构造方法");
    }

    private BookDaoImpl( int connectionNum,String databaseName){
        this.databaseName=databaseName;
        this.connectionNum=connectionNum;
        System.out.println(new Date() +":执行了有参构造方法");
    }
    @Override
    public void save() {
        System.out.println("BookDaoImpl里的save()执行了。。。。。。");
        System.out.println("连接数:"+connectionNum+"     数据库名称:"+databaseName);
    }

}

//测试类
public class App {
    public static void main(String[] args) {
        //获取Ioc容器
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取Bean
        System.out.println("----------Mapper--------------");
       BookDao bookDao=(BookDao) ctx.getBean("bookMapper");
       bookDao.save();

        System.out.println("--------------Service--------------");
        BookService service=(BookService) ctx.getBean("bookService");
        service.save();

    }
}

测试结果:

按类型装配要求类型是唯一的;因此,使用byType时,必须保障容器中相同类型的bean唯一,推荐使用。

2.3.2ByName

以上代码和测试类不变,修改XML文件里面的配置如下:

运行结果:

byName必须保证容器中具有指定名称的bean,因变量名和配置耦合,不推荐使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值