开发框架-Spring

本文详细介绍了Spring框架,从IOC理论推导开始,讲解了Spring的IoC本质、HelloSpring示例、对象创建方式、配置、依赖注入、Bean的作用域、自动装配,以及注解开发、代理模式、AOP和MyBatis的整合。文章还涵盖了Spring框架的历史、优点、作用域、代理模式分类以及事务处理等核心概念,帮助读者深入理解Spring。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring

简介

Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。

然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

  • 2002,首次推出了Spring框架的雏形:interface21框架。
  • Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,与2004年3月24日发布了1.0正式版!
  • Rod Johnson,Spring框架的创始人,同时也是SpringSource的联合创始人。Spring是面向切面编程(AOP)和控制反转(IoC)的容器框架。
  • Spring的基本理念:使现有的技术更加容易地使用,其本身就是一个大杂烩,整合了现有的技术框架。
  • SSH:Struts2+Spring+Hibernate
  • SSM:SpringMVC+Spring+Mybatis

官网:https://spring.io/

GitHub:https://github.com/spring-projects/spring-framework/find/main

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.16</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.16</version>
</dependency>

优点:

  • Spring是一个开源的免费容器(框架)。
  • Spring是一个轻量级的、非入侵式的框架。
  • 控制反转(IOC),面向切面编程(AOP)。
  • 支持事务的处理,对框架整合的支持!

缺点:

  • 因为发展了很久,导致现在糅杂了太多的技术与框架,使得配置变得十分繁琐,人称配置地域!

小结:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!

Spring7大模块:

img

扩展

  • Spring Boot
    • 一个快速开发的脚手架。
    • 基于SpringBoot可以快速开发单个微服务。
    • 约定大于配置。
  • Spring Cloud
    • SpringCloud是基于SpringBoot实现的。

因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring和SpringMVC。

1、IOC理论推导

传统Dao层与服务层:

public interface UserDao {
   
   
    void getUser();
}
public class UserDaoImpl implements UserDao {
   
   
    @Override
    public void getUser() {
   
   
        System.out.println("默认调用UserDao接口!");
    }
}
public interface UserService {
   
   
    void getUser();
}
public class UserServiceImpl implements UserService {
   
   
    UserDao userDao = new UserDaoImpl();
    @Override
    public void getUser() {
   
   
        userDao.getUser();
    }
}

此时,用户实际是调用了Service层的业务,但当用户需求有变动时,例如此时用户并不想要调用默认的UserDao接口,而是想要调用特殊的接口去链接Oracle数据库,解决方法可以是重新写一个UserDao的实现类,继承接口后重写方法。但是在代码量十分庞大的情况下,这种措施无疑是最坏的做法。

假设此时有一个UserDao实现类:

public class UserDaoOracleImpl implements UserDao {
   
   
    @Override
    public void getUser() {
   
   
        System.out.println("Oracle调用UserDao接口!");
    }
}

而这次,并不直接创建一个新的业务实现类,而是在原有的业务实现类进行一些修改:

public class UserServiceImpl implements UserService {
   
   
    private UserDao userDao;
    // 利用Set进行动态实现值的注入!
    public void setUserDao(UserDao userDao) {
   
   
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
   
   
        userDao.getUser();
    }
}

可以发现,以上实例将UserDao作为业务层的属性,并重写了set方法,于是在测试类中,可以这样进行测试:

public class UserServiceTest {
   
   
    public static void main(String[] args) {
   
   
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoOracleImpl());
        userService.getUser();
    }
}

运行的结果并无二异,但此时可以通过setUserDao方法,可以自行选择走哪个UserDao,代码虽然看上去没有进行多大的变动,但是逻辑性却已经发生了翻天覆地的变化。

  • 在更改之前:程序是主动创建的对象,控制权在程序员手中!
  • 使用了Set注入之后:程序不再具有主动性,而是变成了被动接受的对象!

也就是说,这种思想已经从本质上解决了问题,程序员不再需要去管理对象的创建,系统的耦合性大大降低,可以更加专注于业务的实现!这也就是IOC的原型!

1.1 IOC的本质

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

image-20220227170013982

IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。

image-20220227170444229

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

1.2 HelloSpring

1、准备元数据:

@Data
public class Hello {
   
   
    private String str;

}

2、编写beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- id相当于一个变量名, class为需要实例化的对象-->
<!-- property为对象中的属性,而value相当于为属性设置了一个值 -->
<!-- 使用Spring来创建对象,在Spring中这些都成为Bean -->
    <bean id="Hello" class="com.atayin.pojo.Hello">
        <property name="str" value="Spring"/>
    </bean>

</beans>

3、实例化容器

public class HelloTest {
   
   
    public static void main(String[] args) {
   
   
//       获取spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//       取出对象
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello);
    }
}

思考:

  • Hello 对象是谁创建的 ?

    hello 对象是由Spring创建的。

  • Hello 对象的属性是怎么设置的 ?

    hello 对象的属性是由Spring容器设置的。

这个过程就叫控制反转 :

  • 控制 : 谁来控制对象的创建 , 传统应用程序的对象是由程序本身控制创建的 , 使用Spring后 , 对象是由Spring来创建的 .

  • 反转 : 程序本身不创建对象 , 而变成被动的接收对象 。

依赖注入 : 就是利用set方法来进行注入的。假设实体类没有set方法,那么配置文件会报错!

IOC是一种编程思想 , 由主动的编程变成被动的接收,也可以通过newClassPathXmlApplicationContext去浏览一下底层源码。

所谓的IoC,对象由Spring 来创建,管理,装配 !

1.3 IOC创建对象的方式

1、IOC创建对象的默认方式为使用无参构造方法创建对象,当实体类不存在无参构造时,会报错!

<bean id="user" class="com.atayin.pojo.User">
    <property name="name" value="Ayin"/>
</bean>

2、假设需要使用有参构造方法创建对像,一共有以下三种方式:

  • 使用下标赋值:
<bean id="user" class="com.atayin.pojo.User">
    <constructor-arg index="0" value="Ayin"/>
</bean>
  • 使用类型赋值:这种方式并不建议使用,当构造方法拥有数个相同类型的参数时,使用该方法将会出错!
<bean id="user" class="com.atayin.pojo.User">
    <constructor-arg type="java.lang.String" value="Ayin"/>
</bean>
  • 使用参数名赋值:
<bean id="user" class="com.atayin.pojo.User">
    <constructor-arg name="name" value="Ayin"/>
</bean>

2、Spring配置

别名

<alias name="user" alias="ksjfksdjaf"/>

添加别名之后,可以通过别名获取到这个对象:

ApplicationContext context = new ClassPathXmlApplicationContext();
context.getBean("ksjfksdjaf");

当然,并不是取了别名之后,原本的属性名就失效了,调用原属性名依然可以取到这个对象!

Bean

<bean id="user" class="com.atayin.pojo.User" name="user2,u2"></bean>

在bean标签中,name属性也可以取别名,也可以起多个别名。

import

这个标签可以将多个配置文件,导入合并为一个applicationConfig.xml!

<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>

3、依赖注入

依赖:bean对象的创建依赖于容器!

注入:bean对象中所有的属性,由容器来注入!

映射键或值的值或设置值也可以是以下任一元素:

bean | ref | idref | list | set | map | props | value | null

环境搭建

复杂对象:

@Data
public class Address {
   
   
    private Address address;
}

真实测试对象:

@Data
public class Student {
   
   
    private String name;
    private Address address;
    private String[] book;
    private List<String> hobbys;
    private Map<String, String> card;
    private Set<String> games;
    private String wife;
    private Properties info;
}

注入:

       <bean id="address" class="com.atayin.pojo.Address">
            <property name="address" value="北京"/>
        </bean>
        <bean id="student" class="com.atayin.pojo.Student">
<!--            1、普通值注入,value-->
            <property name="name" value="Ayin"/>
<!--            2、Bean注入,ref-->
            <property name="address" ref="address"/>
<!--            数组-->
            <property name="book" >
                <array>
                    <value>红楼梦</value>
                    <value>西游记</value>
                    <value>三国演义</value>
                </array>
            </property>
<!--            List-->
            <property name="hobbys">
                <list>
                    <value></value>
                    <value></value>
                </list>
            </property>
<!--            Map-->
            <property name="card">
                <map>
                    <entry key="身份证" v
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值