Spring framework Day01:spring容器以及bean的装配

一、什么是 spring framework ?

Spring Framework 是一个开源的基于 Java 平台的应用程序开发框架。它提供了一个综合性的编程和配置模型,用于构建企业级的 Java 应用程序。

Spring Framework 的设计宗旨是通过依赖注入(Dependency Injection)和面向切面编程(Aspect-Oriented Programming)等技术降低企业应用程序的复杂性,并提供了一套全面的解决方案。

Spring Framework 的核心功能包括:

1. 控制反转(Inversion of Control,IoC):通过依赖注入的方式,将对象之间的依赖关系由编码实现转变为配置实现,通过配置文件或注解的方式将对象的依赖关系注入到容器中。

2. 面向切面编程(Aspect-Oriented Programming,AOP):提供了一种非侵入式的编程方式,通过切面对横切关注点(如事务管理、日志记录等)进行模块化和管理。

3. 数据访问与集成(Data Access and Integration):提供了对不同数据访问技术的支持,包括 JDBC、ORM 框架(如 Hibernate、MyBatis)、NoSQL 数据库等。

4. Web 开发支持:提供了对 Servlet、MVC 框架、RESTful Web 服务等的支持,简化了 Web 应用的开发和部署。

5. 安全性:提供了对身份验证、授权等安全方面的支持,保护应用程序的安全性。

Spring Framework 还有很多其他的功能模块,如消息队列、缓存、定时任务等,它们可以灵活地组合和使用,根据应用程序的需求进行定制。

总的来说,Spring Framework 提供了一种简化的开发模式和一整套解决方案,帮助开发者构建可测试、可维护、可扩展的企业级 Java 应用程序。它已经成为 Java 开发领域最受欢迎和广泛应用的框架之一。

二、为什么要学习 spring framework?

1、先看图

 企业的使用率达到的 90%,基本上现在的企业级项目都在用 spring 框架进行开发了,如果这还不够体现出 spring 的重要的话,大家可以去招聘网站去看 Java 后端开发的招聘要求,绝对都是需要会 spring 的。有句话说,不会 spring 就等于不会 Java。

1)、提供了一种轻量级的、高效的开发方式:Spring框架可以帮助简化Java应用程序的开发过程,提供了大量的现成解决方案和模块化的特性。通过使用Spring,可以减少开发人员的编码工作量,提高开发效率。
2)、促进了松耦合的开发:Spring框架采用了控制反转(IoC)和面向切面编程(AOP)的设计原则。这使得应用程序的各个组件之间实现松耦合,便于代码的维护和扩展。
3)、提供了丰富的功能模块:Spring框架提供了许多功能模块,如事务管理、安全性、缓存、批处理等。这些模块可以方便地集成到应用程序中,提供了对常见问题的解决方案,并遵循了最佳的企业级开发实践。
4)、支持多种技术整合:Spring框架可以与其他流行的Java技术进行整合,如Hibernate、MyBatis、JPA、RESTful Web服务等。通过整合这些技术,可以构建出更加强大和灵活的应用程序。
5)、社区活跃且资源丰富:Spring框架拥有庞大而活跃的社区,有许多专业的开发者和贡献者。在学习Spring框架时,可以通过社区论坛、博客、教程等途径获取丰富的学习资源和技术支持。

 总而言之,学习Spring框架可以帮助开发人员提高开发效率、降低代码复杂度、实现松耦合的设计,并且能够应用于各种Java应用程序的开发中。这使得Spring成为了Java开发领域一个非常重要的框架。

 2、学习spring framework

这门课程很重要,这是学习 spring 全家桶的基础,如果要学习其他的 spring 框架必须要学好这门课程。

三、开始学习

1、先来看看我们现在代码中的问题

这是我们以前写代码的方式,从图片中看,我们在业务层需要对 dao 实现类进行业务处理时,我们需要 New 一个 dao 接口的实现类出来。但是,现在 dao 接口有两个实现类,我们 New 一个对象已经不能满足我们了,当 dao 接口有多个实现类时,我们需要去 New 多个对象出来,就需要在业务层中去改动代码,每当 dao 接口有新的实现类,业务层就需要改一次代码,新 New 一个对象出来。

所以现在写代码的问题就是:耦合度太高了。

 2、改动

 我们这样一改是不是就不会依赖 dao 层具体的实现了,直接就定一个 dao 变量,不就可以调用方法了吗?不就可以运行起来了吗?答案是不可以,虽然说编译没有错误,但是运行之后就会报空指针异常。

 

 因为 userDao 只是一个空的变量,并没有给它赋值,所以运行会报空指针异常。所以现在问题就是,我们现在需要这个对象,但是我们不能在业务层 New 出一个对象,怎么办呢?

  这就是本章节要讲的内容 Spring 容器和 bean 的装配。

  使用对象的时候,在程序中不再主动使用 New 产生对象,将 New 对象交给外部(spring容器)去做。

3、使用 spring 容器,并装配 bean
1)、 新建一个 Maven 项目,结构如下

2)、导入 spring 依赖 

    <!-- spring 的核心依赖 -->
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.23</version>
        </dependency>

        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.4.5</version>
        </dependency>


    </dependencies>

 导入之后会有五个包

Spring Framework是一个基于Java语言的开源应用框架,其核心部分由5个关键的模块组成:

spring-core.jar:Spring的核心容器,包含了IoC和DI的基本实现。

spring-context.jar:该模块建立在spring-core之上,提供Spring的整合上下文功能,包括对JNDI、EJB、邮件服务、调度任务等的支持。

spring-aop.jar:该模块提供了面向切面编程的特性,允许在程序运行期间动态地将代码横向插入到实现中。

spring-web.jar:该模块提供了一种方便的集成方式,使得Spring能够与Web应用程序进行更加紧密的集成。

spring-webmvc.jar:该模块提供了基于MVC模式的Web应用程序开发框架,通过提供一组可重用的MVC组件,使得开发人员可以轻松构建灵活的Web应用程序。

这五个核心模块可以根据需要进行逐一导入,并且它们也会默认导入其他必需的依赖项。当然,Spring Framework提供了非常丰富的扩展模块和第三方库,用户可以根据自己的需求选择性的导入相关的jar包。

3)、新建一个接口 UserService
public interface UserService {

    void say();

}
4)、 新建一个包 impl,在包下新建一个类,UserService 的实现类 UserServiceImpl
@Slf4j
public class UserServiceImpl implements UserService {

    @Override
    public void say() {
        log.info("Hello spring...");
    }

}

注意:接口本身不能被实例化,因为接口是一个抽象的概念,无法直接创建对象。因此,你不能将接口本身作为bean进行配置和装配。但是,可以将接口的实现类作为bean进行配置和装配。Spring提倡面向接口编程,因此通常我们会定义接口,并在实际的业务类中实现该接口。然后,可以通过配置文件或者注解来将实现类注册为bean,并通过接口类型来引用和使用这些实现类的实例。

5)、在 resources 下新建一个 spring 的 xml 文件 beans.xml,在配置文件中完成 Bean 的装配
<?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 表示当前装配的 Bean 在容器中的唯一标识
         Class 指定 Bean 的完整类名,spring 会使用这个完整类名反射
         创建实例纳入容器中管理
    -->
    <bean id="userService" class="edu.nf.ch01.impl.UserServiceImpl"/>

</beans>

这里要注意了,bean对象不能是接口和抽象类,所以这里的 class 指定的就是 UserServiceImpl 实现类的完整类名。 还有 bean 的 id 在同一个配置文件中是不能重复的。

 6)、测试,新建一个 Mai 类
public class Main {

    public static void main(String[] args) {

        // 创建容器工厂,(在 spring 框架中存在多种不同的容器工厂,每种容器工厂都有自身的特点和功能,例如:
        // 当我们需要通过解析 xml 配置文件来初始化一个容器工厂时,可以使用 ClassPathXmlApplicationContext
        // 这个容器工厂),而这些工厂最终实现的都是 ApplicationContext 接口
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        // 从容器中根据 bean 的 id 获取 bean 的实例
        UserService userService = (UserService) context.getBean("userService");

        // getBean 方法第二个参数执行泛型类型,因此不需要强转
        UserService userService1 = context.getBean("userService", UserService.class);

        // 如果接口的实现类只有一个,可以不需要指定 id,只需要泛型类型即可
        UserService bean = context.getBean(UserService.class);

        userService.say();
        userService1.say();
        bean.say();


    }

}

这是获取 bean实例的三种方法,需要注意的是第三种,我们现在是只有一个实现类,当我们有两个及以上的实现类时,第三种方法就不可以使用了。 

 7)运行

运行之后是不是三种方式都可以调用到我们的 say 方法输出, 这三种方法大家自己选择使用。

四、 自定义工厂

1、在 impl 包下,新建一个 PeopleServiceImpl 实现类,实现 UserService 接口
public class PeopleServiceImpl implements UserService {
    @Override
    public void say() {
        System.out.println("Hello people");
    }
}
2、 在 edu.nf.ch01 包下,新建一个 factory 包,在包下新建一个 PeopleServiceFactory 类
public class PeopleServiceFactory {

    /**
     * 简单工厂,用来创建 PeopleServiceImpl 实例
     * @return
     */
    public UserService create(){
        return new PeopleServiceImpl();
    }

}
自定义工厂,并交给 spring 容器管理。第一种方法是把实现类交给容器管理,这种方法是创建一个简单工厂,这个工厂就负责创建具体的实现类的实例,然后再把这个工厂交给 spring 容器管理,是不是感觉和第一个一样呢。
3、 在 beans.xml,在配置文件中完成 Bean 的装配
    <!-- 装配自定义工厂方式一,spring 会将我们编写的工厂类纳入容器管理 -->
    <bean id="peopleFactoryBean" class="edu.nf.ch01.factory.PeopleServiceFactory"/>
    <!-- 告诉 sprint 使用我们自定义的工厂来创建实例
         factory-bean:引用上面自定义工厂的 id
         factory-method:指定工厂中方法名
     -->
    <bean id="peopleService" factory-bean="peopleFactoryBean" factory-method="create"/>
4、测试
  // 创建容器工厂,(在 spring 框架中存在多种不同的容器工厂,每种容器工厂都有自身的特点和功能,例如:
        // 当我们需要通过解析 xml 配置文件来初始化一个容器工厂时,可以使用 ClassPathXmlApplicationContext
        // 这个容器工厂),而这些工厂最终实现的都是 ApplicationContext 接口
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");


        // 使用自定义工厂创建实例
        UserService peopleService = (UserService) context.getBean("peopleService");
        peopleService.say();

运行结果

五、 使用 FactoryBean 接口自定义工厂(推荐)

1、在 impl 包下,新建一个 StudentServiceImpl 实现类,实现 UserService 接口
public class StudentServiceImpl implements UserService {
    @Override
    public void say() {
        System.out.println("Hello student");
    }
}
2、在  factory 包,在包下新建一个StudentServiceFactoryBean 类,实现 FactoryBean 接口

public class StudentServiceFactoryBean implements FactoryBean<UserService> {

    /**
     * 创建具体的 Bean 实例
     * @return
     * @throws Exception
     */
    @Override
    public UserService getObject() throws Exception {
        return new StudentServiceImpl();
    }

    /**
     * 返回 Bean 实例的 class 类型
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return StudentServiceImpl.class;
    }

}

getObject():该方法返回所创建的 Bean 实例,这是工厂模式的核心方法。

getObjectType():该方法返回创建的对象的类型。

isSingleton():该方法返回 Bean 是否为单例。

这里没有实现 isSingleton() 方法,因为默认就是单例的。

 3、 在 beans.xml,在配置文件中完成 Bean 的装配
  <!-- 自定义工厂方式二,还可以使用 spring 提供的 FactoryBean 接口,创建自定义工厂(推荐)
         当我们从容器中获取 studentService 这个 bean 的时候,
         spring 会调用 studentServiceFactoryBean 的 getObject
         方法返回创建好的对象
     -->
    <bean id="studentService" class="edu.nf.ch01.factory.StudentServiceFactoryBean"/>
4、测试
       // 创建容器工厂,(在 spring 框架中存在多种不同的容器工厂,每种容器工厂都有自身的特点和功能,例如:
        // 当我们需要通过解析 xml 配置文件来初始化一个容器工厂时,可以使用 ClassPathXmlApplicationContext
        // 这个容器工厂),而这些工厂最终实现的都是 ApplicationContext 接口
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        // 实现 FactoryBean 接口创建 Bean 对象
        UserService studentService = (UserService) context.getBean("studentService");
        studentService.say();

运行结果

使用实现了 FactoryBean 接口的自定义工厂有以下好处:

1、灵活性:通过自定义工厂,你可以在创建 Bean 实例之前进行一些自定义逻辑,例如初始化、参数设置等。这样可以提供更大的灵活性来满足特定的需求。

2、隔离性:通过自定义工厂,你可以将一些复杂的实例化逻辑封装在工厂中,从而将其与业务逻辑相分离。这样可以提高代码的可维护性和可读性。

3、控制对象的生命周期:通过自定义工厂,你可以控制所创建的对象的生命周期。例如,可以设置为单例或原型模式,根据需要创建多个对象实例或共享单个对象实例。

4、延迟加载:当你的 Bean 对象很重量级或需要完成一些初始化操作时,你可以通过自定义工厂来延迟加载这些对象。只有当首次访问该对象时才会创建,从而提高应用程序的性能。

5、提供更高层次的抽象:通过自定义工厂,你可以提供一种更高层次的抽象,将复杂的创建过程封装在简单的接口后面。这样可以降低代码耦合度,提高代码的可扩展性和可复用性。

综上所述,使用实现了 FactoryBean 接口的自定义工厂可以为你的应用程序提供更大的灵活性、可控性和可维护性。

 第一个入门案例就完成啦,大家是不是发现还是存在 New 一个对象出来的操作,代码之间的耦合度还是挺高的,该怎么解决呢?在后面的 DI:依赖注入中解决。

六、gitee 案例

案例完整地址:https://gitee.com/qiu-feng1/spring-framework.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值