Spring见解

1.Spring概述

1.1.Spring介绍

Spring是轻量级Java EE应用开源框架(官网: http://spring.io/ ),它由Rod Johnson创为了解决企业级编程开发的复杂性而创建

1.2.简化应用开发体现在哪些方面?

  1. IOC

    解决传统Web开发中硬编码所造成的程序耦合

  2. AOP

    实现在运行期间不修改源代码对程序进行增强

  3. 粘合剂

    Spring是一个超级粘合平台,除了自己提供功能外,还提供整合其他技术和框架的能力

    1.3.Spring的体系结构

    Spring 框架根据功能的不同大体可分为 Data Access/Integration(数据访问与集成)WebAOP、Aspects、Instrumentation(检测)、Messaging(消息处理)Core Container(核心容器)Test
    在这里插入图片描述

  • Core Container: 框架的最基础部分,提供控制反转和依赖注入特性
  • AOP :提供了面向切面的编程的实现
  • Data Access/Integration:简化了持久层的操作
  • Web:提供了Spring MVC Web 框架实现以及与Servlet、WebSocket的集成
  • Test:方便程序的测试

1.4.Spring的发展历程

  • 1997年IBM提出了EJB的思想

  • 1998年,SUN制定开发标准规范EJB1.0

  • 1999年,EJB1.1发布

  • 2001年,EJB2.0发布

  • 2003年,EJB2.1发布

    Rod Johnson(spring之父)

    Expert One-to-One J2EE Design and Development(2002)

    ​ 阐述了J2EE使用EJB开发设计的优点及解决方案

    Expert One-to-One J2EE Development without EJB(2004)

    ​ 阐述了J2EE开发不使用EJB的解决方式(Spring雏形)

  • 2006年,EJB3.0发布

  • 2017年9月发布了Spring的最新版本Spring5.0通用版x

2.Spring IOC

2.1.程序的耦合

  • 耦合:耦合指的就是对象之间的依赖关系。对象之间的耦合越高,维护成本越高。

  • 案例:没有引入IOC容器时系统的Web层、业务层、持久层存在耦合

/**
 * 持久层实现类
 */
public class UserDaoImpl implements UserDao {

    @Override
    public void addUser(){
        System.out.println("insert into tb_user......");
    }
}
/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {
    //硬编码:此处有依赖关系
    private UserDao userDao = new UserDaoImpl();

    public void addUser(){
        userDao.addUser();
    }
}
/**
 * 模拟表现层
 */
public class Client {
    public static void main(String[] args) {
        //硬编码:此处有依赖关系
        UserService userService = new UserServiceImpl();
        userService.addUser();
    }
}
  • 问题分析:

    上边的代码service层在依赖dao层的实现类,此时如果更改dao了层的实现类或此时没有dao层实现类,编译将不能通过。

  • IOC(工厂模式)解耦:

    1. 把所有的dao和service对象使用配置文件配置起来
    2. 当服务器启动时读取配置文件
    3. 把这些对象通过反射创建出来并保存在容器中
    4. 在使用的时候,直接从工厂拿

2.2.IOC解决程序耦合

2.2.1.创建工程

在这里插入图片描述

2.2.2.什么是IOC

  • IOC (Inverse of Control)即控制反转:由ioc容器来创建依赖对象,程序只需要从IOC容器获取创建好的对象。

  • 原来:

    ​ 我们在获取对象时,都是采用new的方式。是主动的。
    在这里插入图片描述

  • 现在:

​ 我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。
在这里插入图片描述
这种被动接收的方式获取对象的思想就是控制反转,它是spring框架的核心之一。

2.2.3.IOC(工厂模式)解耦

案例一

/**
 * bean工厂
 */
public class BeanFactory_v1 {

    /**
     * 获得UserServiceImpl对象
     * @return
     */
    public static UserService getUserService(){
        return new UserServiceImpl();
    }

    /**
     * 获得UserDaoImpl对象
     * @return
     */
    public static UserDao getUserDao(){
        return new UserDaoImpl();
    }
}

问题:我们在开发中会有很多个service和dao,此时工厂类就要添加无数个方法。
案例二

#1、配置要使用的dao和service
UserDao=com.by.dao.UserDaoImpl
UserService=com.by.service.UserServiceImpl
`
``

```csharp
/**
 * bean工厂
 */
public class BeanFactory_v2 {

    private static Properties prop = new Properties();

    /**
     * 根据全类名获取bean对象
     * @param beanName
     * @return
     * @throws ClassNotFoundException
     */
    public static Object getBean(String beanName) {
        try {
            //不能使用:web工程发布后没有src目录
            //InputStream is = new FileInputStream("src/bean.properties");
            InputStream is = 
            BeanFactory_v2.class.getClassLoader()
                .getResourceAsStream("bean.properties");
            prop.load(is);
            return Class.forName(prop.getProperty(beanName)).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(prop.get("UserService"));
        System.out.println(getBean("UserService"));
    }
}
/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {
    
    private UserDao userDao = (UserDao) BeanFactory.getBean("UserDao");

    public void addUser(){
      userDao.addUser();
    }
}

测试:

/**
 * 模拟表现层
 */
public class Client {
    public static void main(String[] args) {
        //直接引用接口实现类
      for (int i = 0; i < 5; i++) {
            UserService userService = 
              (UserService)BeanFactory.getBean("UserService");
            System.out.println(userService);
        }
    }
}

在这里插入图片描述
问题:

  1. 每次都会创建新的对象
  2. 程序运行时才创建对象(读取配置文件)
    案例三
package com.by.factory;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * bean工厂
 */
public class BeanFactory_v3 {

    //定义一个容器,用于存放对象
    private static Map<String, Object> beans = new HashMap<>();

    /**
     * 加载配置文件
     */
    static {
        try {
            //2、读取配置文件
            //不能使用:web工程发布后没有src目录
            //InputStream is = new FileInputStream("src/bean.properties");
            InputStream is = 
            BeanFactory_v3.class.getClassLoader()
                .getResourceAsStream("bean.properties");

            //3、通过反射创建对象,把对象存到容器中
            Properties prop = new Properties();
            prop.load(is);
            Set<Map.Entry<Object, Object>> entrySet = prop.entrySet();
            for (Map.Entry<Object, Object> entry : entrySet) {
                String key = entry.getKey().toString();
                String beanName = entry.getValue().toString();
                Object value = Class.forName(beanName).newInstance();
                beans.put(key, value);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 4、在使用的时候,直接从工厂拿
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName) {
        try {
            return beans.get(beanName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(getBean("UserService"));
    }
}

2.3.Spring的IOC解决程序耦合

2.3.1.创建工程

在这里插入图片描述

2.3.1.1.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.by</groupId>
    <artifactId>Spring_IOC_Xml</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <properties>
        <!-- 项目源码及编译输出的编码 -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!-- 项目编译JDK版本 -->
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    
    <dependencies>
        <!-- Spring常用依赖 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.8.RELEASE</version>
        </dependency>
    </dependencies>
</project>

注意:Jar包彼此存在依赖,只需引入最外层Jar即可由Maven自动将相关依赖Jar引入到项目中。
在这里插入图片描述
​ 核心容器由 beans、core、context 和 expression(Spring Expression Language,SpEL)4个模块组成。

  • spring-beans和spring-core模块是Spring框架的核心模块,包含了控制反转(Inversion of Control,IOC)和依赖注入(Dependency Injection,DI)。BeanFactory使用控制反转对应用程序的配置和依赖性规范与实际的应用程序代码进行了分离。BeanFactory属于延时加载,也就是说在实例化容器对象后并不会自动实例化Bean,只有当Bean被使用时,BeanFactory才会对该 Bean 进行实例化与依赖关系的装配。
  • spring-context模块构架于核心模块之上,扩展了BeanFactory,为它添加了Bean生命周期控制、框架事件体系及资源加载透明化等功能。此外,该模块还提供了许多企业级支持,如邮件访问、远程访问、任务调度等,ApplicationContext 是该模块的核心接口,它的超类是 BeanFactory。与BeanFactory不同,ApplicationContext实例化后会自动对所有的单实例Bean进行实例化与依赖关系的装配,使之处于待用状态。
  • spring-expression 模块是统一表达式语言(EL)的扩展模块,可以查询、管理运行中的对象,同时也可以方便地调用对象方法,以及操作数组、集合等。它的语法类似于传统EL,但提供了额外的功能,最出色的要数函数调用和简单字符串的模板函数。EL的特性是基于Spring产品的需求而设计的,可以非常方便地同Spring IoC进行交互。
2.3.1.2.dao
/**
 * 持久层实现类
 */
public class UserDaoImpl implements UserDao {

    @Override
    public void addUser(){
        System.out.println("insert into tb_user......");
    }
}
2.3.1.3.service
/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {
    //此处有依赖关系
    private UserDao userDao = new UserDaoImpl();

    public void addUser(){
        userDao.addUser();
    }
}

2.3.2.IOC

2.3.2.1.applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入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 
                           http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!--
		2、把对象交给spring来创建
       		id:给对象在容器中提供一个唯一标识。用于获取对象	
		   	class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数
	-->
    <bean id="userDao" class="com.by.dao.UserDaoImpl"></bean>
    <bean id="userService" class="com.by.service.UserServiceImpl"></bean>
</beans>

注意:命名无限制,约定俗成命名有:spring-context.xml、applicationContext.xml、beans.xml

2.3.2.2.测试
/**
 * 模拟表现层
 */
public class Client {
    public static void main(String[] args) {
        //1.使用ApplicationContext接口,就是在获取spring容器
        ApplicationContext ac = new 
            ClassPathXmlApplicationContext("applicationContext.xml");
        //2.根据bean的id获取对象
        UserDao userDao = (UserDao) ac.getBean("userDao");
        System.out.println(userDao);

        UserService userService = (UserService) ac.getBean("userService");
        System.out.println(userService);
        userService.addUser();
    }
}

问题:service层仍然耦合

2.3.3.DI

概述:DI(Dependency Injection)依赖注入,在Spring创建对象的同时,为其属性赋值,称之为依赖注入。

2.3.3.1.构造函数注入

顾名思义,就是使用类中的构造函数,给成员变量赋值。注意,赋值的操作不是我们自己做的,而是通过配置的方式,让spring框架来为我们注入。具体代码如下:

/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;
    private String name;
    private Integer age;

    public UserServiceImpl(UserDao userDao, String name, Integer age) {
        this.userDao = userDao;
        this.name = name;
        this.age = age;
    }

    public void addUser(){
        System.out.println(name+","+age);
        userDao.addUser();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--2、把对象交给spring来创建-->
    <bean id="userDao" class="com.by.dao.UserDaoImpl"></bean>
    <bean id="userService" class="com.by.service.UserServiceImpl">
        <!--
               要求:类中需要提供一个对应参数列表的构造函数。
               标签:constructor-arg
                       ==给谁赋值:==
				           index:指定参数在构造函数参数列表的索引位置
				           name:指定参数在构造函数中的名称
				       ==赋什么值:==
				           value:它能赋的值是基本数据类型和String类型
				           ref:它能赋的值是其他bean类型,也就是说,必须得是在配置文件中配置过的bean
        -->
        <constructor-arg name="userDao" ref="userDao"></constructor-arg>
        <constructor-arg name="name" value="张三"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
    </bean>
</beans>
2.3.3.2.set方法注入

顾名思义,就是在类中提供需要注入成员的set方法。具体代码如下:

/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;
    private String name;
    private Integer age;

    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 addUser(){
        System.out.println(name+","+age);
        userDao.addUser();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--2、把对象交给spring来创建-->
    <bean id="userDao" class="com.by.dao.UserDaoImpl"></bean>
    <bean id="userService" class="com.by.service.UserServiceImpl">
        <!--
               要求:property
               标签:constructor-arg
                       ==给谁赋值:==
				           name:找的是类中set方法后面的部分
				       ==赋什么值:==
				           value:它能赋的值是基本数据类型和String类型
				           ref:它能赋的值是其他bean类型,也就是说,必须得是在配置文件中配置过的bean
        -->
        <property name="userDao" ref="userDao"></property>
        <property name="name" value="张三"></property>
        <property name="age" value="18"></property>
    </bean>
</beans>
2.3.3.3.自动注入

不用在配置中 指定为哪个属性赋值,由spring自动根据某个 “原则” ,在工厂中查找一个bean并为属性注入值。具体代码如下:

/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void addUser(){
        userDao.addUser();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--2、把对象交给spring来创建-->
    <bean id="userDao" class="com.by.dao.UserDaoImpl"></bean>
        <!--autowire="byType":按照类型自动注入值-->
    <bean id="userService" class="com.by.service.UserServiceImpl" autowire="byType">
    </bean>
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--2、把对象交给spring来创建-->
    <bean id="userDao" class="com.by.dao.UserDaoImpl"></bean>
    <!--autowire="byType":按照类型自动注入值-->
    <bean id="userService" class="com.by.service.UserServiceImpl" autowire="byName">
    </bean>
</beans>
2.3.3.4.注入集合类型的属性

顾名思义,就是给类中的集合成员传值,它用的也是set方法注入的方式,只不过变量的数据类型都是集合。我们这里介绍注入数组,List,Set,Map。具体代码如下:

/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;
    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public void addUser(){
        System.out.println(Arrays.toString(myStrs));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        userDao.addUser();
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<!--1、注意:要导入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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--2、把对象交给spring来创建-->
    <bean id="userDao" class="com.by.dao.UserDaoImpl"></bean>
    <bean id="userService" class="com.by.service.UserServiceImpl">
        <!--
                要求:property
                标签:constructor-arg
                        ==给谁赋值:==
				            name:找的是类中set方法后面的部分
				        ==赋什么值:==
				            value:它能赋的值是基本数据类型和String类型
				            ref:它能赋的值是其他bean类型,也就是说,必须得是在配置文件中配置过的bean
        -->
        <property name="userDao" ref="userDao"></property>
        <!-- 给mySet集合注入数据 -->
        <property name="mySet">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </set>
        </property>
        <!-- 注入array数组数据 -->
        <property name="myArray">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>
        <!-- 注入list集合数据 -->
        <property name="myList">
            <list>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </list>
        </property>
        <!-- 注入Map数据 -->
        <property name="myMap">
            <map>
                <entry key="testA" value="aaa"></entry>
                <entry key="testB" value="bbb"></entry>
            </map>
        </property>
    </bean>
</beans>

2.4.Spring中的工厂类

2.4.1.ApplicationContext

ApplicationContext的实现类,如下图:
在这里插入图片描述

  • ClassPathXmlApplicationContext:加载类路径下 Spring 的配置文件
  • FileSystemXmlApplicationContext:加载本地磁盘下 Spring 的配置文件

2.4.2.BeanFactory

spring中工厂的类结构图
在这里插入图片描述
区别:

  • ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public UserServiceImpl() {
        System.out.println("UserServiceImpl对象创建了...");
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void addUser(){
        userDao.addUser();
    }
}
/**
 * 模拟表现层
 */
public class Client {
    public static void main(String[] args) {
        new ClassPathXmlApplicationContext("applicationContext.xml");
        System.out.println("Spring IOC容器创建好了");
    }
}

BeanFactory:是在 getBean 的时候才会创建对象。

/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public UserServiceImpl() {
        System.out.println("UserServiceImpl对象创建了...");
    }

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void addUser(){
        userDao.addUser();
    }
}
/**
 * 模拟表现层
 */
public class Client {
    public static void main(String[] args) {
        new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
        System.out.println("Spring IOC容器创建好了");
    }
}

2.5.bean的作用范围

2.5.1.概述

在Spring中,bean作用域用于确定bean实例应该从哪种类型的Spring容器中返回给调用者。

2.5.2.五种作用域

  • 目前Spring Bean的作用域或者说范围主要有五种:

    作用域说明
    singleton默认值,Bean以单例方式存在spring IoC容器
    prototype每次从容器中调用Bean时都返回一个新的实例,相当于执行newInstance()
    requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
    sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
    applicationWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 ServletContext 域中
  • 可以通过 <bean> 标签的scope 属性控制bean的作用范围,其配置方式如下所示:

    <bean id="..." class="..." scope="singleton"/>
    
  • 需要根据场景决定对象的单例、多例模式

    单例:Service、DAO、SqlSessionFactory(或者是所有的工厂)

    多例:Connection、SqlSession

2.6.bean的生命周期

2.6.1.单例bean

案例

<bean id="userService" class="com.by.service.UserServiceImpl"
      			scope="singleton" init-method="init" destroy-method="destroy">
/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public UserServiceImpl() {
        System.out.println("调用构造方法创建bean...");
    }

    public void setUserDao(UserDao userDao) {
        System.out.println("调用set方法注入值...");
        this.userDao = userDao;
    }

    public void init(){
        System.out.println("调用init方法初始化bean...");
    }

    public void destroy(){
        System.out.println("调用destroy方法销毁bean...");
    }

    public void addUser(){
        userDao.addUser();
    }
}
/** * 模拟表现层 */public class Client {    public static void main(String[] args) {        ClassPathXmlApplicationContext ac =             new ClassPathXmlApplicationContext("applicationContext.xml");        //关闭容器        ac.close();    }}

生命周期:

[容器启动]—>构造方法(实例化)—>set方法(注入)—>init方法(初始化)—>[容器关闭]—>destroy方法(销毁)
在这里插入图片描述

2.5.2.多例bean

案例

<bean id="userService" class="com.by.service.UserServiceImpl"
      			scope="prototype" init-method="init" destroy-method="destroy">
/**
 * 业务层实现类
 */
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    public UserServiceImpl() {
        System.out.println("调用构造方法创建bean...");
    }

    public void setUserDao(UserDao userDao) {
        System.out.println("调用set方法注入值...");
        this.userDao = userDao;
    }

    public void init(){
        System.out.println("调用init方法初始化bean...");
    }

    public void destroy(){
        System.out.println("调用destroy方法销毁bean...");
    }

    public void addUser(){
        userDao.addUser();
    }
}
/**
 * 模拟表现层
 */
public class Client {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = 
            	new ClassPathXmlApplicationContext("applicationContext.xml");
        //使用对象
        ac.getBean("userService");
    }
}

生命周期:

[使用对象]---->构造方法(实例化)—>set方法(注入)—>init方法(初始化)—>[JVM垃圾回收]—>destroy方法(销毁)
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/291735.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB】EEMD_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 EEMD-LSTM神经网络时序预测算法是一种结合了扩展经验模态分解&#xff08;EEMD&#xff09;和长短期记忆神经网络&#xff08;LSTM&#xff09;的时间序列预测方法。 EEMD是一种改进的EM…

spring见解2基于注解的IOC配置

3.基于注解的IOC配置 学习基于注解的IOC配置&#xff0c;大家脑海里首先得有一个认知&#xff0c;即注解配置和xml配置要实现的功能都是一样的&#xff0c;都是要降低程序间的耦合。只是配置的形式不一样。 3.1.创建工程 3.1.1.pom.xml <?xml version"1.0" en…

《论文阅读》基于情绪-原因转换图的共情回复生成

《论文阅读》基于情绪-原因转换图的共情回复生成 前言摘要模型架构图构建回复概念预测回复生成前言 今天为大家带来的是《EMPATHETIC RESPONSE GENERATION VIA EMOTION CAUSE TRANSITION GRAPH》 出版: 时间:2023.2.23 类型:共情对话生成 关键词:图网络;共情回复;情绪…

C++ 实现对战AI五子棋

个人主页&#xff1a;日刷百题 系列专栏&#xff1a;〖C/C小游戏〗〖Linux〗〖数据结构〗 〖C语言〗 &#x1f30e;欢迎各位→点赞&#x1f44d;收藏⭐️留言&#x1f4dd; ​ ​ 前言&#xff1a; 为了能够快速上手一门语言&#xff0c;我们往往在学习了基本语法后&#x…

SoapUI参数传递操作详解

SoapUI 传递参数 本文章主要是通过例子&#xff0c;给大家讲解一下 SoapUI 发送请求时&#xff0c;如何带上参数~ 我们可以先了解下&#xff1a;SoapUI简介&#xff1a;了解这个流行的API测试工具 新建工程 首先新建一个工程&#xff0c;然后在里面进行后续的操作。 填写工程…

【C语言期末】基于VS2022的学生成绩管理系统

诚接计算机专业编程任务(C语言、C、Python、Java、HTML、JavaScript、Vue等)10/15R&#xff0c;如有需要请私信我&#xff0c;或者加我的企鹅号&#xff1a;1404293476 本文资源&#xff1a;https://download.csdn.net/download/weixin_47040861/88702521https://download.csd…

海外数据中心代理与住宅代理:优缺点全面对比

数据中心代理和住宅代理是为了匿名而开发的&#xff0c;通过替换网站眼中您自己的 IP 地址。然而&#xff0c;它们在价格、功能、性能或最佳用例方面存在一些差异。那么&#xff0c;这些代理类型到底有什么相似点和不同点呢&#xff1f; 一、什么是数据中心代理&#xff1f; 1…

CSS 放大旋转动画

<template><div class"container" mouseenter"startAnimation" mouseleave"stopAnimation"><!-- 旋方块 --><div class"box" :class"{ rotate-scale-up: isAnimating }"><!-- 元素内容 -->&l…

视频怎么配上音乐?视频软件轻松配乐

视频怎么配上音乐&#xff1f;视频配乐已经成为了一种重要的表达方式。它能够为视频增添情感&#xff0c;营造氛围&#xff0c;让观众更加深入地理解视频的内容。那么&#xff0c;哪些软件可以给视频配上音乐呢&#xff1f;本文将为你介绍几款优秀软件。 一、清爽视频编辑 清爽…

【Harmony OS - 网络请求】

在一个应用开发中&#xff0c;网络请求是必不可少的&#xff0c;我们一般用的fetch、axios来进行http请求&#xff0c;在鸿蒙中也可以通过createHppt来发生一个http请求&#xff0c;它们都是异步请求返回的Promise&#xff0c;下面我们将介绍’ohos.net.http’和axios这两种方式…

JMeter 插件大全:详细介绍 Jmeter 常用插件

JMeter作为一个开源的接口性能测试工具&#xff0c;其本身的小巧和灵活性给了测试人员很大的帮助&#xff0c;但其本身作为一个开源工具&#xff0c;相比于一些商业工具&#xff08;比如 LoadRunner&#xff09;&#xff0c;在功能的全面性上就稍显不足。这篇博客&#xff0c;就…

特斯拉被比亚迪拉下神坛,马斯克难改命运岁月不如人

当这个消息浮现在我面前时&#xff0c;我几乎不敢相信眼前所见。比亚迪这个我曾无数次在文章中提及的中国车企&#xff0c;终于在2023年完成了伟大的历史任务——以销量突破特斯拉&#xff0c;站上全球电动车王座的宝座&#xff01; 过去我们都习惯于从欧美日韩那里听说汽车的成…

k8s笔记1- 初步认识k8s

k8s简介&#xff1a; kubernetes&#xff0c;俗称k8是&#xff0c;用于自动部署&#xff0c;扩缩和管理容器化应用程序的开源系统&#xff0c;它将组成应用程序的容器&#xff0c;组合成逻辑单元&#xff0c;便于管理和服务发现。 k8s的作用 自动化上线和回滚、存储编排…

张驰咨询:ZENNER真兰标杆展示——2023年六西格玛DMAIC项目出色落下帷幕

告别了旧年&#xff0c;我们跨入了新的一年&#xff01;ZENNER在23年初启动的DMAIC项目在2023年12月25日迎来了总结、收获成果的发布会。 ZENNER真兰集团中国区总裁杨燕明先生&#xff0c;张驰咨询公司的两位精益六西格玛黑带大师专家张驰老师和朱成朝老师&#xff0c;以及真诺…

云卷云舒:构建业务型电信智能运维方法

1 引言 智能运维&#xff08;AIOps-Algorithmic IT Operations基于算法的IT运维&#xff09;是人工智能技术在IT运维领域的运用&#xff0c;引用Gartner 的报告的一段话“未来几年&#xff0c;将近50%的企业将会在他们的业务和IT运维方面采用AIOps&#xff0c;远远高于今天的10…

java基础之java8新特性-默认方法

目录 1.默认方法 jdk8之前的接口 jdk8的接口 默认方法的用途 1.默认方法 jdk8之前的接口 在jdk8之前接口&#xff08;interface&#xff09;中可以定义变量和方法&#xff0c;变量必须是public&#xff0c;static&#xff0c;final的&#xff1b;方法必须是public&#xf…

腾讯云2024年优惠券领取入口及使用教程

腾讯云作为国内领先的云计算服务提供商&#xff0c;一直致力于为用户提供优质、高效、安全可靠的云计算服务。为了回馈广大用户&#xff0c;腾讯云会不定期地推出各种优惠活动&#xff0c;其中最受欢迎的就是优惠券活动。本文将详细介绍腾讯云优惠券的领取入口及使用教程。 一、…

19、BLIP-2

简介 github 通过利用预训练的视觉模型和语言模型来提升多模态效果和降低训练成本&#xff0c;预训练的视觉模型能够提供高质量的视觉表征&#xff0c;预训练的语言模型则提供了强大的语言生成能力。 实现过程 为了弥合模态差距&#xff0c;提出了一个分两个阶段预训练的 Qu…

秋招复习之数组与链表

目录 前言 1 数组 初始化数组&#xff1a; 访问元素 插入元素 删除元素 遍历数组&#xff1a; 查找元素 扩容数组&#xff1a; 数组的优点与局限性 2 链表 初始化链表 插入节点 删除节点 访问节点 查找节点 数组 vs. 链表 常见链表类型 3 列表 初始化列表 访问元素 插入与删…

6. Mybatis 缓存

6. Mybatis 缓存 MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率MyBatis系统中默认定义了两级缓存 一级缓存二级缓存 默认情况下&#xff0c;只有一级缓存&#xff08;SqlSession级别的缓存&#xff0c;也称为本地缓存&…