Spring学习笔记第一天,Spring框架的概述Spring入门案例以及spring中基于xml的IOC配置

Anaconda下安装LabelImg 阅读详情

1. Spring的概述

1.1 Spring是什么

Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 SpringMVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。

1.2 Spring的两大核心是什么?

IoC(Inverse Of Control:反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)是Spring的两大核心。

1.3 Spring的发展历程和优势?

1.3.1 Spring 的发展历程

1997 年 IBM 提出了 EJB 的思想
1998 年, SUN 制定开发标准规范 EJB1.0
1999 年, EJB1.1 发布
2001 年, EJB2.0 发布
2003 年, EJB2.1 发布
2006 年, EJB3.0 发布
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 雏形)
2017 年 9 月份发布了 spring 的最新版本 spring 5.0 通用版(GA)

1.3.2 Spring 的优势

  • 方便解耦,简化开发
    通过 Spring 提供的 IoC 容器,可以将对象间的依赖关系交由 Spring 进行控制,避免硬编码所造成的过度程序耦合。用户也不必再为单例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
  • AOP 编程的支持
    通过 Spring 的 AOP 功能,方便进行面向切面的编程,许多不容易用传统 OOP 实现的功能可以通过 AOP 轻松应付。
  • 声明式事务的支持
    可以将我们从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活的进行事务的管理,提高开发效率和质量。
  • 方便程序的测试
    可以用非容器依赖的编程方式进行几乎所有的测试工作,测试不再是昂贵的操作,而是随手可做的事情。
  • 方便集成各种优秀框架
    Spring 可以降低各种框架的使用难度,提供了对各种优秀框架( Struts、 Hibernate、 Hessian、Quartz等)的直接支持。
  • 降低 JavaEE API 的使用难度
    Spring 对 JavaEE API(如 JDBC、 JavaMail、远程调用等)进行了薄薄的封装层,使这些 API 的使用难度大为降低。
  • Java 源码是经典学习范例
    Spring 的源代码设计精妙、结构清晰、匠心独用,处处体现着大师对 Java 设计模式灵活运用以及对 Java 技术的高深造诣。它的源代码无意是 Java 技术的最佳实践的范例。

1.4 Spring的体系架构

在这里插入图片描述

2. 程序的耦合以及解耦

2.1 JDBC案例

首先创建数据库和表

create database if not exists spring;

use spring;

drop table if exists account;
create table account(
    id int primary key auto_increment,
    name varchar(40),
    money float
)character set utf8 collate utf8_general_ci;

insert into account(name, money) values('aaa',1000);
insert into account(name, money) values('bbb',2000);
insert into account(name, money) values('ccc',3000);

我们先创建一个项目,然后在这个项目中进行我们案例的编写。首先在指定的文件目录下创建一个空的Java项目Spring,删除掉里面的src文件,因为我们要在module中进行编写代码。然后在Spring这个空项目中创建我们Spring学习中的第一个Module命名为day01_01jdbc。

  • 编写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.itheima</groupId>
    <artifactId>day01_01jdbc</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>

</project>
  • 创建一个 JdbcDemo1.java的案例类
public class JdbcDemo1 {
    public static void main(String[] args) throws SQLException {
        //1.注册驱动
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        //2.获取链接
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring", "root", "123456");
        //3.获取操作数据库的预处理对象
        PreparedStatement pstm = conn.prepareStatement("select * from account;");
        //4.执行SQL,得到结果集
        ResultSet rs = pstm.executeQuery();
        //5.遍历结果集
        while (rs.next()) {
            System.out.println(rs.getString("name"));
        }
        //6.释放资源
        rs.close();
        pstm.close();
        conn.close();
    }
}

Module的结构如下:
在这里插入图片描述

2.1 JDBC案例中的问题

  • 程序的耦合
    • 耦合:程序间的依赖关系
      包括:

            类之间的依赖
            方法间的依赖
      
    • 解耦:

        降低程序间的依赖关系
      
    • 实际开发中:

        应该做到,编译期不依赖,运行时才依赖
      
    • 解耦思路:

       第一步:使用反射来穿件对象,而避免使用new关键字。
       第二步:通过读取配置文件来获取要创建的对象的全限定类名
      

在上面的JDBC案例中注册驱动使用了 new 关键字来创建驱动,这样就不利于程序的扩展,当我们想要使用其他的驱动时就更改注册驱动的代码从新编译代码。所以这里我们可以使用反射的方法来注册驱动

// DriverManager.registerDriver(new com.mysql.jdbc.Driver());//更换成下面的代码
Class.forName("com.mysql.jdbc.Driver");

但是这样还有问题,就是这里的驱动写死了也不利于扩展,这时我们就应该使用配置文件的方式来实现。

2.2 工厂模式解耦

2.2.1 之前的数据访问流程

我们在没有学习框架之前都是使用客户端(一般为浏览器)访问 servlet,然后servlet访问service,然后在访问持久层的dao。下面我们就写一遍之前的写法。
我们新建一个Module命名为day01_02factory。项目结构如下:
在这里插入图片描述
新建好Module之后首先编写pom.xml添加 packaging节点

<?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.itheima</groupId>
    <artifactId>day01_02factory</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>
</project>

然后新建一个 IAccountDao.java 的接口

/**
 * 账户的持久层实现类
 */
public interface IAccountDao {

    /**
     * 模拟保存账户的方法
     */
    void saveAccount();
}

然后在建一个 IAccountDao 的实现类 AccountDaoImpl.java

public class AccountDaoImpl implements IAccountDao {
    public void saveAccount() {
        System.out.println("保存了账户...");
    }
}

下面我们创建service层的类,新建 IAccountService.java 接口

/**
 * 账户业务层接口
 */
public interface IAccountService {
    /**
     * 模拟保存账户的方法
     */
    void saveAccount();
}

在新建一个 IAccountService 的实现类 AccountServiceImpl.java

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao = new AccountDaoImpl();

    public void saveAccount() {
        accountDao.saveAccount();
    }
}

然后创建一个Client.java来模拟客户端

/**
 * 模拟一个表现层,用于调用业务层
 */
public class Client {
    public static void main(String[] args) {
        IAccountService service = new AccountServiceImpl();
        service.saveAccount();
    }
}
  • 这样的写法在代码中存在的依赖关系有两个,一个业务层在调用持久层时,还有一个是client里调用业务层。
    private IAccountDao accountDao = new AccountDaoImpl();
    
    IAccountService service = new AccountServiceImpl();
    

这种依赖关系有很强的耦合性,使我们代码的独立性很差。

2.2.2 解决上面提到的依赖

我们在原来的基础上新建一个 com.itheima.factory包,并且在其中新建一个BeanFactory.java

/**
 * 一个创建 Bean 对象的工厂
 * Bean:在计算机英语中,表示有重用组件的含义
 *
 * JavaBean:用Java语言编写的可重用的组件
 *      JavaBean的范围 远大于 实体类
 *
 *      他就是创建我们的service和dao对象的。
 * 		有两个步骤
 *      第一个:需要一个配置文件来配置我们的service和dao
 *           配置的内容:唯一标志=全限定类名 (key=value)
 *      第二个:通过读取配置文件中配置的内容来反射创建对象。
 *      我们的配置可以使用xml也可以是properties
 */
public class BeanFactory {
    //定义一个Properties对象
    private static Properties props;

    //使用静态代码块为 Properties 对象赋值
    static {
        InputStream in = null;
        try {
            //实例化对象
            props = new Properties();
            //获取 Properties 文件流对象
            in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
        } catch (IOException e) { // 如果这个配置文件我们没有读取成功的话,后面的内容就什么也干不了,所以就应该抛出异常
            throw new ExceptionInInitializerError("初始化Properties失败!");
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 根据Bean的名称获取全限定类名通过反射获取bean对象
     * @param beanName
     * @param <T>
     * @return
     */
    public static <T> T getBean(String beanName) {
        T bean = null;
        try {
            String beanPath = props.getProperty(beanName);
            Class<T> clazz = (Class<T>) Class.forName(beanPath);
            bean = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
}

下面我们来修改 AccountDaoImpl.java里的依赖问题

public class AccountServiceImpl implements IAccountService {
    //private IAccountDao accountDao = new AccountDaoImpl();
    // 修改成通过className去使用反射创建对象
    IAccountDao accountDao = BeanFactory.getBean("accountDao");

    public void saveAccount() {
        accountDao.saveAccount();
    }
}

在修改一下Client.java

public class Client {
    public static void main(String[] args) {
        // IAccountService service = new AccountServiceImpl();
        IAccountService service = BeanFactory.getBean("accountService");
        service.saveAccount();
    }
}

现在如果我们删除掉dao.impl包里的实现类和service.impl里的实现类,就会发现,IDE不会提示有异常,也就是说这时dao和service他们的实现类直接没有依赖关系。但是我们运行Client.java里的main方法就会报错。这是以为程序在运行时才有依赖。这样就实现了我们解耦的目的。编译期不依赖,运行时才依赖。
但是这样还有一个问题,就是每次调用 BeanFactory.getBean 都会创建新的实例,我们可以把 BeanFactory.java修改一下

public class BeanFactory {
    //定义一个Properties对象
    private static Properties props;

    //定义一个Map,用于存放我们要创建的对象,我们把它称之为容器
    private static Map<String, Object> beans;

    //使用静态代码块为 Properties 对象赋值
    static {
        InputStream in = null;
        try {
            //实例化对象
            props = new Properties();
            //获取 Properties 文件流对象
            in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);

            // 在加载完Properties后再去对 beans 实例化,把所有要创建的bean类提前创建好。
            beans = new HashMap<String, Object>();
            //取出配置文件中所有的key
            Enumeration<Object> keys = props.keys();
            //遍历这个枚举
            while (keys.hasMoreElements()) {
                //取出每一个key
                String key = keys.nextElement().toString();
                //根据key获取Object的value
                String beanPath = props.getProperty(key);
                Object value = Class.forName(beanPath).newInstance();
                //把key和value存入到容器中
                beans.put(key, value);
            }
        } catch (Exception e) { // 如果这个配置文件我们没有读取成功的话,后面的内容就什么也干不了,所以就应该抛出异常
            throw new ExceptionInInitializerError("初始化Properties失败!");
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static <T> T getBean(String beanName) {
        return (T) beans.get(beanName);
    }
    
    /**
     * 根据Bean的名称获取全限定类名通过反射获取bean对象
     * @param beanName
     * @param <T>
     * @return
     */
//    public static <T> T getBean(String beanName) {
//        T bean = null;
//        try {
//            String beanPath = props.getProperty(beanName);
//            Class<T> clazz = (Class<T>) Class.forName(beanPath);
//            bean = clazz.newInstance();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return bean;
//    }
}

这样在通过 BeanFactory.getBean 方法返回的实例就都是单例的啦。

3. IOC概念和Spring中的IOC

控制反转(Inversion of Control,英文缩写IOC)把创建对象的权利交给框架是框架的重要特征,并非是面向对象编程的专用术语。它包括依赖注入(Dependency Injection,简称DI)和依赖查找(Dependency Lookup)。
IOC-Inversion of Control,译为控制反转,是一种遵循依赖倒置原则的代码设计思想。所谓依赖倒置,就是把原本的高层建筑依赖底层建筑“倒置”过来,变成底层建筑依赖高层建筑。高层建筑决定需要什么,底层去实现这样的需求,但是高层并不用管底层是怎么实现的。这样就不会出现“牵一发动全身”的情况。
  而控制反转就是把传统程序中需要实现对象的创建、代码的依赖,反转给一个专门的"第三方"即容器来实现,即将创建和查找依赖对象的控制权交给容器,由容器将对象进行组合注入,实现对象与对象的松耦合,便于功能的复用,使程序的体系结构更灵活。
  
明确 ioc 的作用:

削减计算机程序的耦合(解除我们代码中的依赖关系)。也就是说IOC只能解决程序间的依赖关系,别的什么都做不了。

3.1 Spring中基于xml的IOC环境搭建

下面我就进行使用spring进行bean对象的创建来实现上面类似的功能。首先在原来的工程上新建一个Module命名为day01_03spring
首先我们修改pom.xml文件,导入依赖的jar包,spring的maven坐标可以在Maven这里找到,根据需要自行选择。

<?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.itheima</groupId>
    <artifactId>day01_03spring</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging> <!-- 项目打包方式为jar包 -->

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
    </dependencies>

</project>

然后我们把上一个Module(就是名为day01_02factory)中的src/main/java下的文件拷贝到当前的这个Module的src/mian/java里。
然后我们把factory包和其中的java文件都删除掉因为我们不在使用这个工厂类来创建对象,我们要是用spring来创建。
然后,修改AccountServiceImpl.java把其中使用 工厂 类创建对象的代码删除掉。这个使用new的方式创建对象保证暂时不报错。

public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao = new AccountDaoImpl();
    public void saveAccount() {
        accountDao.saveAccount();
    }
}

下面我们来编写spring的配置文件,在src.main.resources里新建一个bean.xml文件,并且导入spring的约束,然后编写要创建的对象的id和全限定类名。

<?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">

    <!--把对象的创建交给spring来管理-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>
    <bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>
</beans>

然后修改ui下的Client.java

public class Client {
    /**
     * 获取Spring的IOC核心容器,并根据id获取对象
     * @param args
     */
    public static void main(String[] args) {
        //1. 获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取bean对象
        IAccountService as = (IAccountService) ac.getBean("accountService");
        IAccountDao adao = ac.getBean("accountDao", IAccountDao.class);
        System.out.println(as);
        System.out.println(adao);
    }
}

运行一下main方法控制台输出如下,配置成功。
在这里插入图片描述

3.1.1 Spring的IOC核心容器的两个接口ApplicationContext和BeanFactory

ApplicationContext接口的三个常用实现类

  • ClassPathXmlApplicationContext:它可以加载类路径下的配置文件,要求配置文件必须在类路径下。不在的话就加载不了(推荐使用)
  • FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置文件(必须要有访问权限)
  • AnnotationXmlConfigApplicationContext:它适用于读取注解创建容器的。(在后一天的内容中说明)

3.1.2 核心容器的两个接口引发的问题:

ApplicationContext:单例对象适用(更多是使用这个接口)

  • 它在构建对象核心容器时,创建对象采用的策略是采用立即加载的方式。也就是说,只要一读取完配置文件就马上创建配置文件中配置的对象。

BeanFactory:多例对象适用

  • 它在构建对象核心容器时,创建对象时采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。

下面我们来验证一下ApplicationContext在创建对象时采用的策略是采用立即加载的方式。
首先给AccountServiceImpl.java加一个构造函数

public class AccountServiceImpl implements IAccountService {
	...
    public AccountServiceImpl() {
        System.out.println("对象被创建了...");
    }
    ...
}

然后修改一下Client.java里的main方法

public static void main(String[] args) {
        //1. 获取核心容器对象
        // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        ApplicationContext ac = new FileSystemXmlApplicationContext("D:\\Myproject\\JavaProject\\IDEA\\Tutorial\\Spring\\day01_03spring\\src\\main\\resources\\bean.xml");

        //2.根据id获取bean对象
        IAccountService as = (IAccountService) ac.getBean("accountService");
        IAccountDao adao = ac.getBean("accountDao", IAccountDao.class);

        System.out.println(as);
        System.out.println(adao);

然后使用debug模式运行一下这个main方法,在根据id获取bean对象的那里打断点,我们会发现当程序运行到这里的时候,控制台已经输出了 “对象被创建了…”。说明ApplicationContext在创建对象时采用的策略是采用立即加载的方式。
下面我们也可以验证一下BeanFactory创建对象时采取的策略是采用延迟加载的方式,mian方法修改如下

public static void main(String[] args) {
        //1. 获取核心容器对象
        Resource resource = new ClassPathResource("bean.xml");
        BeanFactory factory = new XmlBeanFactory(resource);
        //2.根据id获取bean对象
        IAccountService as1 = (IAccountService) factory.getBean("accountService");
        IAccountDao adao1 = factory.getBean("accountDao", IAccountDao.class);

        System.out.println(as1);
        System.out.println(adao1);
    }

然后使用debug模式运行一下这个main方法,在根据id获取bean对象的那一句打断点,我们会发现当程序运行到这里的时候,控制台没有输出了 “对象被创建了…”。继续运行到后面一句发现控制台才输出“对象被创建了…”说明了BeanFactory创建对象时采取的策略是采用延迟加载的方式。

3.2 spring中的bean的细节

3.2.1 spring中bean的细节之三种创建Bean对象的方式

我们在原来的项目中新建一个Module命名为day01_04bean,然后修改pom.xml文件添加打包方式和导入spring的依赖。然后把day01_03spring下的src/main里的文件复制到当前项目的src/main里。然后删除调用dao包和其中的java文件,因为我们现在主要展示bean创建的细节。
我们修改一下Client.java里的main方法

public class Client {
    /*
     * @param args
     */
    public static void main(String[] args) {
        //1. 获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取bean对象
        IAccountService as = (IAccountService) ac.getBean("accountService");
        as.saveAccount();
        System.out.println(as);
    }
}

然后我们创建一个com.itheima.factor包来模拟框架中的工厂类。然后在其中创建两个java类,InstanceFactory和StaticFactory,

/**
 1. 模拟一个工厂类,该类可能存在于jar包中的,我们无法通过修改源码的方式来提供默认构造函数
 */
public class InstanceFactory {
    public IAccountService getAccountService() {
        return new AccountServiceImpl();
    }
}
/**
 2. 模拟一个工厂类,该类可能存在于jar包中的,我们无法通过修改源码的方式来提供默认构造函数
 */
public class StaticFactory {
    //模拟一个工厂类中的静态方法
    public static IAccountService getAccountService() {
        return new AccountServiceImpl();
    }
}

下面我们就来修改bean.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">

    <!--把对象的创建交给spring来管理-->
    <!--spring对bean的管理细节
        1.创建bean的三种方式
        2.bean对象的作用范围
        3.bean对象的生命周期
    -->
    <!-- 创建bean的三种方式 -->
    <!-- 第一种方式就是使用默认构造函数创建。
        在spring的配置文件中使用bean标签,配以id和class属性之后,且没有其他属性和标签时。
        采用的就是默认构造函数创建bean对象,此时如果类中没有默认的构造函数(就是空参构造函数),则对象无法创建。
    -->
    <!--<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"></bean>-->

    <!-- 第二种方式:使用普通工厂中的方法创建对象(使用某个类中的方法来创建对象,并存入spring容器)
        比如:accountService这个对象是用 instanceFactory 这个工厂对象的 getAccountService 这个方法获取的
    -->
    <!--<bean id="instanceFactory" class="com.itheima.factory.InstanceFactory"></bean>
    <bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>-->

    <!--第三种方式:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象并存入spring容器)-->
    <bean id="accountService" class="com.itheima.factory.StaticFactory" factory-method="getAccountService"></bean>
</beans>

依次打开每一种方式下的bean标签,然后运行main方法,就会发现这三种方式都是可以的。当我们要创建的对象没有提供默认构造函数时就可以使用后面的两种方法。

3.2.2 spring中bean的细节之作用范围

bean 标签的 scope 属性:
作用:用于指定bean的作用范围
取值:常用的是 单例的和多例的

1. singleton:单例的(默认的)
2. prototype:多例的
3. request:作用于web应用的请求范围
4. session:作用于web应用的会话范围
5. global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session

我们在上一个Module的基础上修改一下bean.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">
    <!-- bean的作用范围调整
        bean标签的scope属性:
            作用:用于指定bean的作用范围
            取值:常用的是 单例的和多例的
                 singleton:单例的(默认的)
                 prototype:多例的
                 request:作用于web应用的请求范围
                 session:作用于web应用的会话范围
                 global-session:作用于集群环境的会话范围(全局会话范围),当不是集群环境时,它就是session
    -->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="singleton"></bean>
</beans>

然后再修改一下Client.java里的main方法

public class Client {
    /*
     * @param args
     */
    public static void main(String[] args) {
        //1. 获取核心容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取bean对象
        IAccountService as = (IAccountService) ac.getBean("accountService");
        IAccountService as1 = (IAccountService) ac.getBean("accountService");
        System.out.println(as == as1);
    }
}

控制台输出如下,从图中可以看出AccountServiceImpl的构造方法只执行了一次, as 和 as1是同一个对象。
在这里插入图片描述
我们把bean.xml文件中bean标签的 scope 属性更改为 prototype,然后在一次运行main方法,控制台输出如下,可以看出AccountServiceImpl的构造方法执行了两次, as 和 as1不是同一个对象。
在这里插入图片描述

3.2.3 spring中bean的细节之生命周期

bean 对象的生命周期

生命周期单例对象多例对象
出生当容器创建时对象出生当我们使用对象时,spring框架帮我们创建
活着只要容器还在,对象化就一直活着对象只要在使用过程中,对象化就一直活着
死亡容器销毁,对象消亡当对象长时间不用,且没有别的对象引用时,由java的垃圾回收器回收
总结单例对象的生命周期和容器相同

bean 关于生命周期的两个属性 init-method、destroy-method

init-method:对象的初始化时的方法,在调用类的构造函数之后调用。
destroy-method:对象的销毁时调用的方法

我们来演示一下对象的初始化和销毁,修改一下AccountServiceImpl.java

public class AccountServiceImpl implements IAccountService {
    public AccountServiceImpl() {
        System.out.println("对象被创建了...");
    }

    public void saveAccount() {
        System.out.println("service 中的saveAccount方法执行了");
    }

    public void init() {
        System.out.println("service 对象初始化了");
    }

    public void destroy() {
        System.out.println("service 对象销毁了");
    }
}

修改bean.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">
    <!-- bean 对象的生命周期
        单例对象
            出生:当容器创建时对象出生
            活着:只要容器还在,对象化就一直活着
            死亡:容器销毁,对象消亡
            总结:单例对象的生命周期和容器相同
        多例对象
            出生:当我们使用对象时,spring框架帮我们创建
            活着:对象只要在使用过程中,对象化就一直活着
            死亡:当对象长时间不用,且没有别的对象引用时,由java的垃圾回收器回收。
     -->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="prototype" init-method="init" destroy-method="destroy"></bean>
</beans>

然后修改一下Client.java里的main方法,注意 ApplicationContext 为接口,其中没有定义close()方法,所以这个类型的引用就无法调用close方法。

public class Client {
    public static void main(String[] args) {
        //1. 获取核心容器对象
        // 由于close()方法不在接口 ApplicationContext 中定义,所以 如果使用多态,ApplicationContext这个类型的ac是不能调用close方法的
        // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.根据id获取bean对象
        IAccountService as = (IAccountService) ac.getBean("accountService");
        as.saveAccount();
        //手动发关闭容器
        ac.close();
    }
}

我们首先把 bean.xml里的bean标签的属性scope赋值为 singleton 让对象单例的被创建。运行一下main方法,控制台输出如下,
在这里插入图片描述
下面我们把bean.xml里的bean标签的属性scope赋值为 prototype 让对象多例的被创建,运行一下main方法,控制台输出如下,我们发现没有调用 AccountServiceImpl 对象的 destroy 方法。这是因为使用多例时,对象只要在使用过程中,对象就一直活着,当对象长时间不用,且没有别的对象引用时,才会由java的垃圾回收器回收。
在这里插入图片描述

4. 依赖注入

依赖注入: Dependency Injection。 它是 spring 框架核心 ioc 的具体实现。 我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。ioc 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。那这种业务层和持久层的依赖关系,在使用 spring 之后, 就让 spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

把有依赖关系的类放到容器中,解析出这些类的实例,就是依赖注入。目的是实现类的解耦。
比如:Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。

框架会把符合依赖关系的对象通过JavaBean属性或者构造函数传递给需要的对象。通过JavaBean属性注射依赖关系的做法称为设值方法注入(Setter Injection);将依赖关系作为构造函数参数传入的做法称为构造器注入(Constructor Injection),还有一种就是使用注解配置(明天的内容)

依赖注入:
        Dependency Injection
IOC的作用:
        降低程序间的耦合(依赖关系)
依赖关系的管理:
        以后都交给了spring来维护
在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明
依赖关系的维护,就称之为依赖注入。

依赖注入:

能注入的数据:有三种

	基本类型和String
	其他bean类型(在配置文件中或者注解配置过的bean)
	复杂类型/集合类型
	
注入的方式有三种:

	第一种:使用构造函数注入
	第二种:使用set方法注入
	第三种:使用注解注入(明天的内容)

4.1 构造函数注入

我们先讲解一下 构造函数注入
比如,我们的 AccountServiceImpl 类中有三个属性分别为 name,age,birthday。代码如下

public class AccountServiceImpl implements IAccountService {
    //如果是经常变化的数据,并不适用于注入的方式
    //这些属性只是用于演示
    private String name;
    private Integer age;
    private Date birthday;

    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public void saveAccount() {
        System.out.println("service 中的saveAccount方法执行了" + this.toString());
    }

    @Override
    public String toString() {
        return "AccountServiceImpl{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }
}

我们在使用 构造函数注入 时要在bean标签里使用一个标签 constructor-org
标签出现的位置,bean标签的内部

  • 标签中的属性
    1. type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个活某些参数的类型
    2. index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
    3. name:用于指定给构造函数指定名称的参数赋值(常用)
      以上三个属性用于指定给构造函数中哪个参数赋值
    4. value:用于提供基本类型和String类型的数据
    5. ref:用于指定其他的bean类数据(可以理解为引用的数据类型)。它指的是在spring的IOC核心容器中出现过的bean对象

优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
弊端:改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。

bean.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">

    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <constructor-arg type="java.lang.String" index="0" value="张三"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg index="2" ref="now"></constructor-arg>
    </bean>
    <!--配置一个日期对象-->
    <bean id="now" class="java.util.Date"></bean>
</beans>

我们执行以下Client.java里的main方法,控制台输出如下,说明数据的注入成功。
在这里插入图片描述

4.2 set方法注入

我先在 com.itheima.service.impl包里在创建一个 AccountServiceImpl2.java用于测试 set方法注入。要想使用set方法注入就必须提供set方法。

public class AccountServiceImpl2 implements IAccountService {
    //如果是经常变化的数据,并不适用于注入的方式
    private String name;
    private Integer age;
    private Date birthday;
    //要想使用set方法的注入方式就必须提供set方法
    public void setUserName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public void saveAccount() {
        System.out.println("service 中的saveAccount方法执行了" + this.toString());
    }

    @Override
    public String toString() {
        return "AccountServiceImpl{name='" + name + "', age=" + age + ", birthday=" + birthday + '}';
    }
}

set方法注入 (更常用的方式)
使用的标签:property
出现的位置:bean标签的内部

  • 标签的属性:
    1. name:用于指定注入时所调用的set方法名称(去掉set的方法名称,比如法名称为 setUserName 那么这里的 name的值就为 userName ,注意u要小写)
    2. value:用于提供基本类型和String类型的数据
    3. ref:用于指定其他的bean类数据(可以理解为引用的数据类型)。它指的是在spring的IOC核心容器中出现过的bean对象

优势:创建对象时没有明确的限制,可以直接使用默认构造函数
弊端:如果有某个成员必须有值,则获取对象时有可能set方法没有执行

bean.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">

    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <constructor-arg type="java.lang.String" index="0" value="张三"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg index="2" ref="now"></constructor-arg>
    </bean>
    <!--配置一个日期对象-->
    <bean id="now" class="java.util.Date"></bean>

    <bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl2">
        <property name="userName" value="李四"></property>
        <property name="age" value="20"></property>
        <property name="birthday" ref="now"></property>
    </bean>
</beans>

下面修改一下Client.java里的main方法

public class Client {
    public static void main(String[] args) {
        //1. 获取核心容器对象
        // 由于close()方法不在接口 ApplicationContext 中定义,所以 如果使用多态,ApplicationContext这个类型的ac是不能调用close方法的
        // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

        //2.根据id获取bean对象
//        IAccountService as = (IAccountService) ac.getBean("accountService");
//        as.saveAccount();

        IAccountService as = (IAccountService) ac.getBean("accountService2");
        as.saveAccount();
    }
}

运行一下main方法,控制台输出如下,说明数据的注入成功
在这里插入图片描述

4.3 复杂类型/集合类型的注入

spring的依赖注入**除了基本数据类型的数据注入外还可以注入复杂数据类型,比如Array、List、Set、Map、Properties等 **,其注入的方法还是用的 set方法的注入方式 。下面我们就来演示一下。
先在 com.itheima.service.impl包里在创建一个 AccountServiceImpl3.java用于测试 复杂类型/集合类型的注入。

public class AccountServiceImpl3 implements IAccountService {
    private String[] myStr;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String, String> myMap;
    private Properties myProps;
	//因为原理上还是set方法的注入,所以要提供set方法。
    public void setMyStr(String[] myStr) {
        this.myStr = myStr;
    }

    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 setMyProps(Properties myProps) {
        this.myProps = myProps;
    }

    public void saveAccount() {
        System.out.println(toString());
    }

    @Override
    public String toString() {
        return "AccountServiceImpl3{" + '\n'+
                "myStr=" + Arrays.toString(myStr) + ",\n"+
                "myList=" + myList + ",\n"+
                "mySet=" + mySet + ",\n"+
                "myMap=" + myMap + ",\n"+
                "myProps=" + myProps + ",\n"+
                '}';
    }
}

复杂类型的注入(集合类型的注入)

用于给List结构集合注入的标签:list、array、set
用于给Map结构集合注入的标签:map、props
结构相同、标签可以互换

修改对于的bean.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">

    <!-- spring中的依赖注入
        依赖注入:
            Dependency Injection
        IOC的作用:
            降低程序间的耦合(依赖关系)
        依赖关系的管理:
            以后都交给了spring来维护
        在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明
        依赖关系的维护,就称之为依赖注入。
        依赖注入:
            能注入的数据:有三种
                基本类型和String
                其他bean类型(在配置文件中或者注解配置过的bean)
                复杂类型/集合类型
            注入的方式有三种:
                第一种:使用构造函数提供
                第二种:使用set方法提供
                第三种:使用注解提供(明天的内容)
     -->

    <!--构造函数注入-->
    <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
        <constructor-arg type="java.lang.String" index="0" value="张三"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg index="2" ref="now"></constructor-arg>
    </bean>
    <!--配置一个日期对象-->
    <bean id="now" class="java.util.Date"></bean>

    <!-- set方法注入 (更常用的方式)-->
    <bean id="accountService2" class="com.itheima.service.impl.AccountServiceImpl2">
        <property name="userName" value="李四"></property>
        <property name="age" value="20"></property>
        <property name="birthday" ref="now"></property>
    </bean>

    <!-- 复杂类型的注入(集合类型的注入)
        用于给List结构集合注入的标签:list、array、set
        用于给Map结构集合注入的标签:map、props
        结构相同、标签可以互换
    -->
    <bean id="accountService3" class="com.itheima.service.impl.AccountServiceImpl3">
        <property name="myStr">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>

        <property name="myList">
            <list>
                <value>listAAA</value>
                <value>listBBB</value>
                <value>listCCC</value>
            </list>
        </property>

        <property name="mySet">
            <set>
                <value>setAAA</value>
                <value>setBBB</value>
                <value>setCCC</value>
            </set>
        </property>

        <property name="myMap">
            <map>
                <entry key="name" value="张三"></entry>
                <entry key="gender" value="男"></entry>
                <entry key="address"> <!-- 这样写也是正确的 -->
                    <value>上海市</value>
                </entry>
            </map>
        </property>

        <property name="myProps">
            <props>
                <prop key="driver">com.mysql.jdbc.Driver</prop>
                <prop key="url">jdbc:mysql://localhost:3306/spring</prop>
                <prop key="userName">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
    </bean>
</beans>

然后我们在修改一下Client.java里的main方法

public class Client {
    public static void main(String[] args) {
        //1. 获取核心容器对象
        // 由于close()方法不在接口 ApplicationContext 中定义,所以 如果使用多态,ApplicationContext这个类型的ac是不能调用close方法的
        // ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

        //2.根据id获取bean对象
//        IAccountService as = (IAccountService) ac.getBean("accountService");
//        as.saveAccount();

//        IAccountService as = (IAccountService) ac.getBean("accountService2");
//        as.saveAccount();

        IAccountService as = (IAccountService) ac.getBean("accountService3");
        as.saveAccount();
    }
}

运行一下main方法控制台输出如下:我们可以看出输入已经被注入到对象中了。
在这里插入图片描述
至此我们应该对spring的作用、功能和使用有了一定的了解。

参考文档
Spring
Spring Framework
Spring官方说明文档
IOC和DI基础
什么是依赖注入

【Unity动画优化插件】BT - OptiAnimX —— AAA级动画优化框架深度剖析 BT - OptiAnimX 是一款面向 Unity 的高性能动画优化框架,核心目标是解决多角色动画场景中的性能瓶颈问题。该插件对标《战争机器5》和《巫师3》等 AAA 游戏中的动画优化技术,通过一整套自动化与智能化的优化策略,将动画性能提升与视觉质量控制结合在一起。它适用于从移动端、VR 到高端 PC 的多平台项目,尤其在“多人角色 + 高频动画”的场景中表现突出,例如 MMO、开放世界、动作游戏等。BT - OptiAnimX 本质上是一套“动画性能调度系统”,而不仅仅是优化工具。 阅读详情

相关推荐

C++开发基础之掌握常用的三种异步编程模型

以上是三种常见的C++异步编程模型,每种模型都有其适用的场景和特点。根据具体需求,你可以选择合适的模型来进行异步编程。

dotnet研习社 2175

【Spring】一个spring简单实例

spring的基础知识就不讲了,直接上代码吧! 为了方便大家创建文件,先把project的结构放在这 1.新建一个projec,本帖设置的名字为“project-hello”. 2. 新建一个package,这里取名为“com.company.project”. 3. 新建一个class,名为“Hello”。代码为: package com.company.project; public class Hello { private String name; pub.

一定要站在自己热爱的生活里闪闪发光 7万+

想在瑞芯微RK3588上跑视频分类模型?避开3D卷积这个坑,试试这几种NPU友好的方案

本文探讨了在瑞芯微RK3588上部署视频分类模型时如何避开3D卷积的性能陷阱,提供了三种NPU友好的替代方案:MobileNetV2+GRU组合、Temporal Shift Module(TSM)和帧级池化。这些方案在保持较高准确率的同时,充分利用RKNPU的硬件加速能力,显著提升推理效率。文章还分享了从模型转换到部署优化的完整流程和实战经验。

weixin_28724319的博客 417

Spring到底是如何来实现IOC和DI?案例解析入门篇

Spring 🍭SSM框架01:Spring的IoC和DI,以及手把手带你创建Spring核心配置文件 🍭SSM框架02:从0-1学习Spring配置文件 🍭为什么要学Spring?学什么?怎么学? 一、入门案例 介绍完Spring的核心概念后,接下来我们得思考一个问题就是,Spring到底是如何来实现IOC和DI的,那接下来就通过一些简单的入门案例,来演示下具体实现过程: 1.1 IOC入门案例 对于入门案例,我们得先分析思路然后再代码实现, 1.1.1 入门案例思路分析 (1)Spring是使用容器来管

黑马程序员官方博客 1050

逆向分析第一步:如何从HEX文件‘还原’出单片机的原始程序与数据?

本文详细解析了如何从HEX文件逆向分析出单片机的原始程序与数据,涵盖了固件逆向的底层逻辑与实践。通过介绍HEX文件的结构、内存映像重建技术以及专业工具链的使用,帮助读者掌握从十六进制数据到可执行代码的完整流程,适用于嵌入式系统开发和逆向工程领域。

weixin_29745609的博客 315

【局部路径规划模块地图算法】基于势场地图的VFH、VFH+、VFH*算法(附C++代码)

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!本文先对基于地图的方法–VFH、VFH+、VFH*算法做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章提示:以下是本篇文章正文内容。

qq_35635374的博客 1686

Spring 整合 Web 项目实例

Spring 是目前各个企业必备的技术,也是各个框架技术需要整合的组件。Spring 生态技术目前已经是互联网开发中必不可少的一个技术栈。 相信读者能通过本文的学习,打下一定的 Spring 技能基础,为后面 Spring 生态的扩展技术做充足的准备。 本文大致包含了以下几方面的讲解: Spring IoC 容器初始化,将 Spring IoC 容器中所有的 Bean 实例化为对象,将各个 Bean 依赖的属性值注入; 在 Web 应用服务器启动时,Spring IoC 容器初始化过程; 根据三层结构拆分

草原印象的博客 599

04 HCM CPI SF集成-员工集成(一)

将员工主数据和组织数据从SAP Successfactors Employee CentraI复制到SAPERP或SAP S/4HANA,SAP SF CPI HCM集成

SAP CPI 146

使用Spring框架的17个开源项目

发表于2小时前| 29次阅读| 来源ProgramCreek| 0 条评论| 作者Consuelo 开源Spring项目管理企业应用文档管理电子商务 摘要:Spring作为现在最优秀的框架之一,已被广泛的使用。不管你觉得Spring框架学习起来是简单还是复杂,这里都为你介绍使用Spring框架创建的开源项目。希望能对你的开发工作带来灵感,一起来看看都有哪些开源项目!

Java/Android/IOS/前端/云计算 4756

dToF直方图之美_deadtime死区时间

IMX459的死区时间可以在6ns,这个时间是什么级别,车载激光雷达激光器的光脉宽一般都在4ns以上,也就是这个时间贴近去SPAD的死区时间,这就导致了pile up会非常弱,不会有太多数量的光子计数堆积,加上某些SPAD设计,对TDC有一些更深入的考量,所以不需要去校正pile up算法。Sensor层面决定了pile up的复杂程度,如果一个dToF的SPAD一致性非常好,那么pile up校正可以简单到极致,也就是一句代码的事,比如IMX611,优秀到不需要后端去考虑校正pile up。

致力于lidar应用开发 2147

域适应分类:MCD论文笔记——Maximum Classifier Discrepancy for Unsupervised Domain Adaptation

域适应分类:MCD论文笔记——Maximum Classifier Discrepancy for Unsupervised Domain Adaptation

qq_50001789的博客 1005

35款优秀的 SpringBoot/SpringCloud 开源项目,开发脚手架,总有一款适合你!

SpringBoot 是一个非常流行的 Java 框架,它可以帮助开发者快速构建应用程序。他不仅继承了 Spring 框架原有的优秀特性,而且还通过简化配置来进一步简化了 Spring 应用的整个搭建和开发过程。最近,小编蹲点各大开源网站、社区等,终于被我找到了35款基于 SpringBoot/ SpringCloud 技术体系的一些开源框架。这些项目大都具备一些很完善的功能,并且均采用了当下比较流行的技术栈。无论是日常学习,还是当做自己项目搭建的脚手架,都是非常合适的。

竹林幽深 4977

Open3D 进阶(22)间接平差法拟合空间曲线

空间曲线拟合在电力线三维重建中有着广泛的应用,本文利用python使用间接平差法对三维空间曲线的拟合进行代码实现。

点云侠的博客 1057

【SSM】Spring学习笔记1: IoC的XML配置

文章基于。

2301_76391858的博客 1219

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Spring IoC容器的概念以及基于XML的IoC装配【一万字】

基于最新Spring 5.x,详细介绍了Spring入门案例的搭建,以及基于XML的核心IoC机制的配置和使用。适合Spring初学者。

终生学习践行者 4601

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Spring5 学习总结—框架概述,入门案例,IOC容器

Spring 框架概述 Spring 是轻量级的开源的 JavaEE框架 Spring 可以解决企业应用开发的复杂性 Spring 有俩个核心部分 : IOC 和 Aop IOC :控制反转,把创建对象过程交给 Spring 进行管理 Aop :面向切面,不修改源代码进行功能增强 Spring 特点: 方便解耦,简化开发 Aop 编程支持 方便程序的测试 方便和其它框架进行整合 如:MyBat...

m0_52901132的博客 552

【Spring(二)】IoC入门案例(XML版)

上篇文章我们讲了IOC和DI两个核心概念,本篇文章我们会在Spring的环境下来实现它们💪💪。在实现IoC的入门案例中,我们先进行了导如入Spring坐标🚩🚩,没这一步,连配置文件的结构我们都找不到🤣🤣,接下来定义Spring管理的类(接口)🎈🎈,第三步创建Spring配置文件,配置对应类作为Spring管理的Bean🎉🎉,我们需要注意的是Bean定义时id属性在同一个上下文中不能重复🚨🚨,,第四步初始化Spring容器,通过容器来拿配置好的Bean,一定要记住。

hihielite的博客 948

Spring概述与核心概念学习 -- Spring入门(一)

为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。(博客的参考源码以及可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)Spring Framework 是一个功能强大的 Java 应用程序框架,旨在提供高效且可扩展的开发环境。它结合了轻量级的容器(IOC)和依赖注入(DI)

m0_74825003的博客 854

Spring从入门到入土——概述以及IOC理论推导

Spring 概述以及IOC理论推导Spring 概述优点组成IoC基础IoC本质 相关文章: 跟着官网学spring—快速入门指南 跟着官网学Spring—构建RESTful Web服务 Spring 概述 优点 Spring是一个开源免费的框架、容器 Spring是一个轻量级的框架、非侵入式的 控制反转Ioc、面向切面Aop 对事务的支持以及对框架的支持 总之: spring是一个轻量级的...

冢狐的私人空间 1732

spring框架的概述以及spring中基于xml的ioc配置

1.spring的概述 什么是spring?

qq_40395100的博客 229

spring框架的概述以及spring中基于XML的IOC配置

spring中基于XML的IOC配置

OneFine的技术博客 553

Spring入门-IOC和XML配置

目录Spring入门1 Spring简介1.1 什么是框架1.2 框架的作用1.3 Spring是什么1.4 Spring的体系结构1.5 Spring的发展历史1.6 Spring容器概念(简单来说就是MAP)2 IoC简介2.1 优质程序代码的制作原则2.2 耦合与内聚2.3 工厂模式发展史2.4 Spring发展历程2.5 IoC3 入门案例3.1 案例环境说明3.2)IoC入门案例制作步骤3.2.1 IoC入门案例制作步骤-13.2.2 IoC入门案例制作步骤-23.2.3 IoC入门案例制作步骤-

赵广陆 1051

Spring学习笔记第二天,Spring基于xml的IOC和注解的IOC以及IOC的案例

经过了第一天的学习,我们对spring框架应该有了一定的了解。对于使用xml配置的方式也应该会使用了。今天我们就来学习spring基于注解的IOC以及IOC的案例。 1 Spring中IOC的常用注解 在我们上一天的学习中我们使用的是xml对ioc进行配置,配置的方式如下 <bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="" init-method="" destroy-method

Code_Boy_Code的博客 711

Spring-学习笔记05【基于XML的IOC的案例】

Spring-学习笔记05【基于XML的IOC的案例】

upward 1186

Spring框架的概述以及Spring中基于XML的IOC配置

Spring框架的概述以及Spring中基于XML的IOC配置 Spring概述 Spring:是分层的 Java SE/EE 应用full-stack轻量级开源框架 spring两大核心: IOC(Inverse Of Control:反转控制) AOP(Aspect Oriented Programming:面向切面编程) spring发展历程和优势:Rod Johnson(spring之父) spring体系结构 程序的耦合及解耦 耦合:程序之间的依赖关系 包括: 类之间的依赖 方

weixin_37652146的博客 144

Spring概述&Spring基于XML的IOC

耦合是软件结构中各模块之间相互连接的一种度量,耦合强弱取决于模块间接口的复杂程度、进入或访问一个模块的点以及通过接口的数据。数据耦合是最低的一种耦合形式,系统中一般都存在这种类型的耦合,因为为了完成一些有意义的功能,往往需要将某些模块的输出数据作为另 一些模块的输入数据。在软件工程中,耦合指的就是就是对象之间的依赖性。总结: 耦合是影响软件复杂程度和设计质量的一个重要因素,在设计上我们应采用以下原则:如果模块间必须存在耦合,就尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,尽量避免使用内容耦合。

2401_87878486的博客 752

【Spring学习笔记】—— (一)Spring框架概述 + 基于XML的IoC配置

1. Spring是什么 我们常说的 Spring 实际上 是指 `SpringFramework` ,而 SpringFramework 只是 Spring 家族的的一个分支而已。 Spring是分层的 Java SE/EE应用 full-stack 轻量级开源框架,**以 IOC(Inverse Of Control: 反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核**,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层

小牛肉的博客 1096
上一篇: MyBatis学习笔记第四天、MyBatis延迟加载、MyBatis缓存、MyBatis使用注解开发
下一篇: Spring学习笔记第二天,Spring基于xml的IOC和注解的IOC以及IOC的案例
Code_Boy_Code
博客等级 码龄9年 650粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值