1.spring框架-----spring framework bean基础配置 bean生命周期

目录

一、spring framework

1.IoC控制反转(Inversion of Control)

2.DI依赖注入(Dependency Injection)

3.bean基础配置

4.bean实例化 

4.1构造方法

4.2静态工厂

4.3实例工厂

5.bean的生命周期


一、spring framework

springframework 是spring 里面的一个基础开源框架,主要用于javaee的企业开发。

  图源

1.IoC控制反转(Inversion of Control)

不需要自己主动创建对象,由外部提供对象,对象创建控制权由程序转移到外部,称为控制反转。spring提供一个容器,称为IoC容器,IoC容器负责创建对象、初始化等一系列工作,被创建或管理的对象在IoC容器中统称为Bean

 IoC 在其他语言中也有应用,并非 Spirng 特有。 IoC 容器是 Spring 用来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。

2.DI依赖注入(Dependency Injection)

在容器中建立bean和bean之间依赖关系的整个过程,称为依赖注入

‘高内聚,低耦合’

项目中每个模块之间相互联系的紧密程度,模块之间联系越紧密,耦合性越高,模块的独立性就越差

模块中各个元素之间的联系的紧密程度,如果各个元素(语句、程序段)之间的联系程度越高,内聚性越高

而我们设计软件需要的是“高内聚,低耦合”

使用IOC容器管理Bean,在IOC容器中把有依赖关系的都进行绑定,在使用对象时就可以之间从IOC容器中获取,并且所有的bean已经绑定好依赖关系,降低了耦合性,修改代码的时候不需要全部更改

3.bean基础配置

spring默认提供的bean是单例的

想要修改成不是单例的可以在配置文件中修改

singleton默认为单例 prototype为非单例

 scope="prototype"

为什么bean默认为单例?

bean为单例的意思是在Spring的IOC容器中只会有该类的一个对象 bean对象只有一个就避免了对象的频繁创建与销毁,达到了bean对象的复用,性能高

bean在容器中是单例的,会不会产生线程安全问题?

如果对象是有状态对象,即该对象有成员变量可以用来存储数据的, 因为所有请求线程共用一个bean对象,所以会存在线程安全问题。 如果对象是无状态对象,即该对象没有成员变量没有进行数据存储的, 因方法中的局部变量在方法调用完成后会被销毁,所以不会存在线程安全问题。

4.bean实例化 

 实例化bean的三种方式,构造方法,静态工厂和实例工厂

bean本质上就是对象,对象在new的时候会使用构造方法完成,那创建bean也是使用构造方法完成 的。

4.1构造方法

Spring底层使用的是类的无参构造方法。

先创建接口BookDao和类BookDaoImpl

public interface BookDao {
    public void save();
}


public class BookDaoImpl implements BookDao {
    public BookDaoImpl() {
        System.out.println("book dao constructor is running ....");
    }

    public void save() {
        System.out.println("book dao save ...");
    }

}

 applicationContext.xml

<!--配置bean-->

 <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

编写运行程序 

public class AppForLifeCycle {
    public static void main( String[] args ) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
        bookDao1.save();

    }
}

​

 

4.2静态工厂

先创建接口BookDao和类BookDaoImpl

public interface BookDao {
    public void save();
}


public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }

}

创建一个工厂类BookDaoFactory并提供一个静态方法 

public class BookDaoFactory {
    public static BookDao getOrderDao(){
        return new BookDaoImpl();
    }
}

配置文件 

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

 <bean id="bookDao" class="com.itheima.factory.BookDaoFactory" factory-method="getOrderDao"/>

编写AppForLifeCycle运行类,在类中通过工厂获取对象 

public class AppForLifeCycle {
    public static void main( String[] args ) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao orderDao = (BookDao) ctx.getBean("bookDao");
        orderDao.save();
    }
}

 

 在工厂的静态方法中,我们除了new对象还可以做其他的一些业务操作,

4.3实例工厂

 先创建接口BookDao和类BookDaoImpl

public interface BookDao {
    public void save();
}


public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ...");
    }

}

创建一个工厂类BookDaoFactory并提供一个方法 -----此时不是静态方法

public class BookDaoFactory {
    public BookDao getOrderDao(){
        return new BookDaoImpl();
    }
}

配置文件 

实例化工厂运行的顺序是:

创建实例化工厂对象,对应的是第一行配置

调用对象中的方法来创建bean,对应的是第二行配置

factory-bean:工厂的实例对象 factory-method:工厂对象中的具体创建对象的方法名

  <bean id="bookDaoFactory" class="com.itheima.factory.BookDaoFactory"/>
  <bean id="bookDao" factory-method="getOrderDao" factory-bean="bookDaoFactory"/>

编写AppForLifeCycle运行类

public class AppForLifeCycle {
    public static void main( String[] args ) {
        BookDaoFactory bookDaoFactory = new BookDaoFactory();
        BookDao bookDao = bookDaoFactory.getOrderDao();
        bookDao.save();
    }
}

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

创建一个BookDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法

public class BookDaoFactoryBean implements FactoryBean<BookDao> {

   //代替原始实例工厂中创建对象的方法
    public BookDao getObject() throws Exception {
        return new BookDaoImpl();
    }

   //返回所创建类的Class对象
    public Class<?> getObjectType() {
        return BookDao.class;
    }
}

配置文件

  <bean id="bookDaoFactory" class="com.itheima.factory.BookDaoFactoryBean"/>

别的不需要更改

getObject(),被重写后,在方法中进行对象的创建并返回

getObjectType(),被重写后,主要返回的是被创建类的Class对象

isSingleton(),设置对象是否为单例,默认是true单例

5.bean的生命周期

项目中添加BookDao、BookDaoImpl、BookService和BookServiceImpl类

public interface BookDao {
    public void save();
}


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 destroy(){
        System.out.println("destroy...");
    }

}


public interface BookService {
    public void save();
}

public class BookServiceImpl implements BookService {
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }

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

为BookDao添加生命周期的控制方法,具体的控制有两个阶段:

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

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

init-method="init" destroy-method="destroy"

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

运行方法

public class AppForLifeCycle {
    public static void main( String[] args ) {
        ApplicationContext ctx = new
                ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();

    }
}

init方法执行了,但是destroy方法却未执行

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

解决办法1close关闭容器

想要执行destroy方法,ApplicationContext中没有close方法 需要将ApplicationContext更换成ClassPathXmlApplicationContext,实例化对象ctx之后,调用close()方法

public class AppForLifeCycle {
    public static void main( String[] args ) {
        ClassPathXmlApplicationContext ctx = new
                ClassPathXmlApplicationContext("applicationContext.xml");
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
        ctx.close();

    }
}

解决办法1注册钩子关闭容器

将ApplicationContext更换成ClassPathXmlApplicationContext,实例化对象ctx之后,调用registerShutdownHook()方法

public class AppForLifeCycle {
    public static void main( String[] args ) {
        ClassPathXmlApplicationContext ctx = new
                ClassPathXmlApplicationContext("applicationContext.xml");
        ctx.registerShutdownHook();
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();

    }
}

相同点:这两种都能用来关闭容器

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

close()强制退出

事实上还有更简便的方法,Spring提供了两个接口来完成生命周期的控制,好处是可以不用再进行配置init-method和 destroy-method

修改BookServiceImpl类,添加两个接口InitializingBean, DisposableBean并实现接口中的两个方法afterPropertiesSet和destroy

初始化方法会在类中属性设置之后执行

public class BookServiceImpl implements BookService, InitializingBean, DisposableBean{
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }

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

    @Override
    public void destroy() throws Exception {
        System.out.println("service destroy");
    }

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

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习java的张三

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值