spring两大核心技术 IoC AOP

Spring可以整合目前市面上大部分的框架

MyBatis

MyBatis-plus

Struts

Struts2

Hibernate

Spring官网展示了Spring包含的技术,发展到今天,Spring已经形成了一种开发的生态圈,Spring提供的若干个项目,每个项目用于完成特定的功能。

项目学习顺序:

Spring Framework:作为底层架构,运行的基础

Spring Boot:简化开发,加快开发速度

Spring Cloud:分布开发工具

Spring发展史:Spring1.0 to Spring5.0

Spring4.0架构图

 IoC(Inversion of Control:控制反转)

在目前的代码书写中,业务层和数据层的耦合度偏高

数据层定义类(BookDaoImpl)继承自接口(BookDao),类中定义了实现的方法(save), 业务层实例化类的一个对象(bookdao),对象调用方法。

但是如果类中实现方法改变了(BookDaoImpl),这时就需要对业务层代码进行改变,此时需要重新部署,编译。

IoC的思想是:使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象的控制权由程序转移到外部,此思想称为控制反转

Spring技术对IoC进行了实现

IoC,IoC容器,Bean,DI(Dependency Injection:依赖注入)

IoC实现的目标是充分解耦

IoC容器和DI是实现手段

IoC实现的效果是:使用对象时不仅可以直接从IoC容器中获取,并且获取到的bean已经绑定了所有的依赖关系

IoC入门案例

1.导入Spring的坐标Spring-context,对应版本,pom.xml文件中导入dependency

                 

2.创建Spring配置文件,在resource文件夹里

3.获取IoC容器,获取Bean

DI入门案例

5.删除实现类使用new方法生成的对象

6.这时就没有对象了,使用setter方法来创建一个对象

7. 在配置文件中配置Bean的关系

name和ref虽然一样,但是两者表示意义不同,name表示现在实现类的属性的名称,作用是去找到bookDao的属性,并且调用setter方法进行对象注入,ref表示在配置文件中的Bean的id,作用是是让Spring在IoC容器中找到id是bookDao的bean对象,给bookService注入bookDao对象

 Bean基础配置

bean的id必须是唯一的

bean的name属性:可以使用多个别名

获取bean可以通过id,name来获取

bean的作用范围

IoC容器中默认对象是单例的,同一个bean创造出来的对象是同一个地址,是相同的。

如果想要创建一个非单例的对象,就需要修改bean的scope属性

scope属性默认为singleton(单例)

设置属性为prototype后,一个bean创造出来的两个对象就是两个对象了。

bean的这种单例属性适合需要复用的对象 

bean的实例化过程(容器是怎么创建对象的)

1.使用构造方法创建对象

Spring底层启用的是反射,即使类中的构造方法是private属性的,也可以访问使用。注意构造方法必须是无参的,否则Spring在访问方法时会出现错误。这种方法很常用

2.使用静态工厂实例化

工厂类:使用工厂来创建对象,创建一个工厂类,并定义一个静态方法

//静态工厂创建对象
public class OrderDaoFactory {
    public static OrderDao getOrderDao(){
        return new OrderDaoImpl();
    }
}

使用静态工厂创建一个对象

public class AppForInstanceOrder {
    public static void main(String[] args) {
    //通过静态工厂创建对象
    OrderDao orderDao = OrderDaoFactory.getOrderDao();
    orderDao.save();
    }
}

在Spring中怎么使用静态工厂呢

在Spring配置文件中加入以下内容,如果不加入factory-method,那么只能产生一个factory对象,不能产生我们想要的orderDao对象

class:工厂类的类全名 factory-mehod:具体工厂类中创建对象的方法名 

 这种方法可以在工厂里面添加其他的业务操作,这些操作用工厂类方式比较方便,如果只是我们自己new一个新对象出来,只能new一个对象,无法执行业务操作。静态工厂方法主要在以前的老系统操作常见,目前了解即可

实例工厂和Spring管理实例工厂

与静态工厂类似,创建一个工厂类,但是提供一个实例方法,

public class UserDaoFactory {
    public UserDao getUserDao(){
    return new UserDaoImpl();
    }
}

创建一个运行类,在类中创建一个实例工厂对象,再通过实例工厂对象来创建一个对象 

public class AppForInstanceUser {
    public static void main(String[] args) {
    //创建实例工厂对象
    UserDaoFactory userDaoFactory = new UserDaoFactory();
    //通过实例工厂对象创建对象
    UserDao userDao = userDaoFactory.getUserDao();
    userDao.save();
}

实例工厂创建类怎么通过Spring来实现呢

在Spring配置文件中加入以下代码

 

 在运行类中,运行以下代码,会从IoC容器中取出对应bean

public class AppForInstanceUser {
    public static void main(String[] args) {
    ApplicationContext ctx = new
    ClassPathXmlApplicationContext("applicationContext.xml");
    UserDao userDao = (UserDao) ctx.getBean("userDao");    //在IoC中找到id为userDao的bean,接着Spring管理实例化工厂开始运行
    userDao.save();
    }
}

Spring管理实例化工厂还是比较麻烦

所以Spring为了简化这种配置方式就提供了一种叫FactoryBean的方式来简化开发

FactoryBean

//创建一个类实现FactoryBean接口
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
    //代替原始实例工厂中创建对象的方法
    public UserDao getObject() throws Exception {
    return new UserDaoImpl();
    }
    //返回所创建类的Class对象
    public Class<?> getObjectType() {
    return UserDao.class;
    }
}

和实例工厂的方法看着类似,但是在Spring配置文件中可以看出两者的不同,使用FactoryBean方式的配置代码简单很多

FactoryBean接口中有三个方法

T getObject() throws Exception;    //:getObject(),被重写后,在方法中进行对象的创建并返回 
Class<?> getObjectType();    //getObjectType(),被重写后,主要返回的是被创建类的Class对象

default boolean isSingleton() {
return true;
}
//没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认true为单例

 

 

这种方法的应用性很广。很实用

bean的生命周期

创建bean之后,为bean添加生命周期的控制方法如下

bean创建之后,想要添加内容,比如用来初始化需要用到资源

bean销毁之前,想要添加内容,比如用来释放用到的资源

public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }
    //表示bean初始化对应的操作
    public void init(){
        System.out.println("init...");
    }
    //表示bean销毁前对应的操作
    public void destory(){
        System.out.println("destory...");
   }
}

在配置文件中添加生命周期

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl" init-method="init"
destroy-method="destory"/>

运行运行文件后,结果如下

 从结果中可以看出,init方法执行了,但是destroy方法却未执行,这是为什么呢?

Spring的IOC容器是运行在JVM中 运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器获取bean对象,然后调方法执行,main方法执行完后,JVM退出,这个时候IOC容器中的bean还没有来得及销毁就已经结束了 所以没有调用对应的destroy方法

怎么才能调用destory()方法呢

提供以下方法

close关闭容器

ApplicationContext中没有close方法

需要将ApplicationContext更换成ClassPathXmlApplicationContext

ClassPathXmlApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");

 再调用ctx的close()方法

ctx.close()

此时再运行文件,destory中的内容可以被运行

 注册钩子关闭容器

在容器未关闭之前,提前设置好回调函数,让JVM在退出之前回调此函数来关闭容器

调用ctx的registerShutdownHook()方法

 

 两种方法的作用相同,都可以关闭容器

不同点:close()是在调用的时候关闭,registerShutdownHook()是在JVM退出前调用关闭。

但在类中添加初始化和销毁代码,还要再Spring中添加配置,比较麻烦,所以Spring中自带了两个接口来实现以上操作,不需要再配置init和destory配置

 

在BookServiceImpl类中添加两个接口

public class BookServiceImpl implements BookService,InitializingBean,
        DisposableBean
    //两个接口的实现方法
    @Override
    public void destroy() throws Exception {
        System.out.println("Service destory");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Service init");
    }

运行之后, 

 

 

更多推荐