• 1.spring框架-----spring framework


    目录

    一、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

    1. public interface BookDao {
    2. public void save();
    3. }
    4. public class BookDaoImpl implements BookDao {
    5. public BookDaoImpl() {
    6. System.out.println("book dao constructor is running ....");
    7. }
    8. public void save() {
    9. System.out.println("book dao save ...");
    10. }
    11. }

     applicationContext.xml

    1. "bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>

    编写运行程序 

    1. public class AppForLifeCycle {
    2. public static void main( String[] args ) {
    3. ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    4. BookDao bookDao1 = (BookDao) ctx.getBean("bookDao");
    5. bookDao1.save();
    6. }
    7. }

     

    4.2静态工厂

    先创建接口BookDao和类BookDaoImpl

    1. public interface BookDao {
    2. public void save();
    3. }
    4. public class BookDaoImpl implements BookDao {
    5. public void save() {
    6. System.out.println("book dao save ...");
    7. }
    8. }

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

    1. public class BookDaoFactory {
    2. public static BookDao getOrderDao(){
    3. return new BookDaoImpl();
    4. }
    5. }

    配置文件 

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

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

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

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

     

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

    4.3实例工厂

     先创建接口BookDao和类BookDaoImpl

    1. public interface BookDao {
    2. public void save();
    3. }
    4. public class BookDaoImpl implements BookDao {
    5. public void save() {
    6. System.out.println("book dao save ...");
    7. }
    8. }

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

    1. public class BookDaoFactory {
    2. public BookDao getOrderDao(){
    3. return new BookDaoImpl();
    4. }
    5. }

    配置文件 

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

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

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

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

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

    编写AppForLifeCycle运行类

    1. public class AppForLifeCycle {
    2. public static void main( String[] args ) {
    3. BookDaoFactory bookDaoFactory = new BookDaoFactory();
    4. BookDao bookDao = bookDaoFactory.getOrderDao();
    5. bookDao.save();
    6. }
    7. }

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

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

    1. public class BookDaoFactoryBean implements FactoryBean {
    2. //代替原始实例工厂中创建对象的方法
    3. public BookDao getObject() throws Exception {
    4. return new BookDaoImpl();
    5. }
    6. //返回所创建类的Class对象
    7. public Class getObjectType() {
    8. return BookDao.class;
    9. }
    10. }

    配置文件

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

    别的不需要更改

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

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

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

    5.bean的生命周期

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

    1. public interface BookDao {
    2. public void save();
    3. }
    4. public class BookDaoImpl implements BookDao {
    5. public void save() {
    6. System.out.println("book dao save ...");
    7. }
    8. //表示bean初始化对应的操作
    9. public void init(){
    10. System.out.println("init...");
    11. }
    12. //表示bean销毁前对应的操作
    13. public void destroy(){
    14. System.out.println("destroy...");
    15. }
    16. }
    17. public interface BookService {
    18. public void save();
    19. }
    20. public class BookServiceImpl implements BookService {
    21. private BookDao bookDao;
    22. public void save() {
    23. System.out.println("book service save ...");
    24. bookDao.save();
    25. }
    26. public void setBookDao(BookDao bookDao) {
    27. this.bookDao = bookDao;
    28. }
    29. }

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

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

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

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

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

    运行方法

    1. public class AppForLifeCycle {
    2. public static void main( String[] args ) {
    3. ApplicationContext ctx = new
    4. ClassPathXmlApplicationContext("applicationContext.xml");
    5. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    6. bookDao.save();
    7. }
    8. }

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

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

    解决办法1close关闭容器

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

    1. public class AppForLifeCycle {
    2. public static void main( String[] args ) {
    3. ClassPathXmlApplicationContext ctx = new
    4. ClassPathXmlApplicationContext("applicationContext.xml");
    5. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    6. bookDao.save();
    7. ctx.close();
    8. }
    9. }

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

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

    1. public class AppForLifeCycle {
    2. public static void main( String[] args ) {
    3. ClassPathXmlApplicationContext ctx = new
    4. ClassPathXmlApplicationContext("applicationContext.xml");
    5. ctx.registerShutdownHook();
    6. BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    7. bookDao.save();
    8. }
    9. }

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

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

    close()强制退出

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

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

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

    1. public class BookServiceImpl implements BookService, InitializingBean, DisposableBean{
    2. private BookDao bookDao;
    3. public void save() {
    4. System.out.println("book service save ...");
    5. bookDao.save();
    6. }
    7. public void setBookDao(BookDao bookDao) {
    8. this.bookDao = bookDao;
    9. }
    10. @Override
    11. public void destroy() throws Exception {
    12. System.out.println("service destroy");
    13. }
    14. @Override
    15. public void afterPropertiesSet() throws Exception {
    16. System.out.println("service init");
    17. }
    18. }

     

  • 相关阅读:
    我,5年Java开发,99.9%技术都会……开始靠八股文面试
    Node.js+vue校内二手物品交易系统tdv06-vscode前后端分离
    Java Socket网络编程
    【由浅入深_打牢基础】HOST头攻击
    C++语法——详细剖析类成员函数在内存中存储形式(包括静态)
    element-ui框架的el-dialog弹出框被遮罩层挡住了/el-drawer....会生成v-model元素的组件被遮罩层挡住
    Element Plus阻止 el-dropdown、el-switch等冒泡事件
    《安富莱嵌入式周报》第279期:强劲的代码片段搜索工具,卡内基梅隆大学安全可靠C编码标准,Nordic发布双频WiFi6 nRF7002芯片
    samba 共享目录write permission deny问题修复 可读取内容但不可修改 删除 新增文件
    AnatoMask论文汇总
  • 原文地址:https://blog.csdn.net/qq_46235384/article/details/127396565