Spring:Spring简介、IOC、AOP【一】

本文介绍了Spring框架的起源、优点和核心概念,包括控制反转(IOC)和依赖注入(DI)。重点讲解了如何通过XML配置、构造注入和set方式实现DI,以及Spring Boot对简化配置的影响。此外,还讨论了Bean作用域和不同注入方式的应用。

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

下一篇:Spring:Spring简介、IOC、AOP【二】
项目地址:https://github.com/hpp3501/spring-demo

1. Spring

1.1 简介

  • 创始人 Rod Johnson
  • 2002年,首次推出了Spring框架的雏形:interface21框架
  • 2004年,interface21框架经过不断的优化升级,于2004年3月24发布了1.0正式版Spring框 架。
  • spring理念:使现有的技术更容易使用,本身整合了市面上大多的技术

1.2 优点

  • spring是要给开源的免费的框架
  • spring是轻量级、非入侵式的框架 (在框架中引入spring,不会改变原框架的结构)
  • 控制反转(IOC)、面向切面编程(AOP)
  • 支持事务的处理,支持对框架的整合

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

1.3 弊端

由于发展的迅速,慢慢的违背了最初的理念!配置变得繁琐。不过后来的SpringBoot解决了配置繁琐的问题。

1.4 组成

在这里插入图片描述

1.5 拓展

  • Spring Boot

    • 一个快速开发的脚手架
    • 基于SpringBoot可以快速开发单体架构
    • 约定大于配置
  • Spring Cloud

    • SpringCloud是基于SpringBoot实现的。

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

2. 控制反转-IOC

理论推导

控制反转IOC(Inversion of control)不是一种技术,而是一种思想。多种方式都已经很好的实现了IOC,比如xml配置或者注解。

1.UserDao 接口

package com.kuang.dao;

public interface UserDao {
    void getUser();
}

2.UserDaoImpl 实现类

package com.kuang.dao;

public class UserDaoImpl implements UserDao {
    public void getUser() {
        System.out.println("获取默认用户的数据");
    }
}
package com.kuang.dao;

public class UserDaoMysqlImpl implements UserDao{
    public void getUser() {
        System.out.println("Mysql获取默认用户数据");
    }
}

3.UserService 业务接口

package com.kuang.service;

public interface UserService {
    void getUser();
}

4.UserServiceImpl 业务实现类

package com.kuang.service;

import com.kuang.dao.UserDao;

public class UserServiceImpl implements UserService {

    //region 原来的方式,每次增加一个userDao的实现类都需要修改UserServiceImpl
    //private UserDao userDao = new UserDaoImpl();
    //private UserDao userDao = new UserDaoMysqlImpl();
    //private UserDao userDao = new UserDaoOracleImpl();
    //endregion

    //region新的方式,通过set注入值,将变化放在用户层,而UserServiceImpl则不需要改变
    private UserDao userDao;
    //利用set进行动态注入值
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    //endregion

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

在我们之前的业务中,用户的需求可能回影响原来的代码,我们需要根据用户的需求去修改原代码!如果程序代码量十分大,修改一次的成本代价也会十分的大。

public class UserServiceImpl implements UserService {
    //region 原来的方式,每次增加一个userDao的实现类都需要修改UserServiceImpl
    //private UserDao userDao = new UserDaoImpl();
    //private UserDao userDao = new UserDaoMysqlImpl();
    //private UserDao userDao = new UserDaoOracleImpl();
    //endregion

    //region新的方式,通过set注入值,将变化放在用户层,而UserServiceImpl则不需要改变
    private UserDao userDao;
    //利用set进行动态注入值
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }
    //endregion
}

测试类

import com.kuang.dao.UserDaoMysqlImpl;
import com.kuang.service.UserServiceImpl;

public class MyTest {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoMysqlImpl());
        userService.getUser();
    }
}
  • 之前,程序是主动创建对象!控制权在开发人员手中。
  • 使用了set注入之后,程序不再具有主动性,而是被动的接收对象。

这种思想,从本质上解决了问题。开发人员不用再去管理对象的创建了,很大的降低了系统的耦合性,开发人员可以更专注于业务的实现。这就是IOC的原型。 、

3. 通过xml配置理解控制反转

创建一个Hello对象

package com.kuang.pojo;

public class Hello {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

添加一个配置文件
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201014161803185.png#pic_center

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

    <!--使用Spring来创建对象,再Spring这些成为Bean-->
    <bean id="hello" class="com.kuang.pojo.Hello">
        <property name="str" value="Spring" />
    </bean>
</beans>

创建一个测试类

import com.kuang.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        //获取spring上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //对象都在spring中管理了,要使用的话直接取出来就可以了
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
}

传统的程序,对象的创建是由程序控制的。上面的例子中,Hello对象的创建没有直接去new实例化,而是交给Spring去创建,这就是通过xml方式实现的控制反转。再添加新的对象时,不需要去修改程序,只用修改xml配置即可。

4. IOC创建对象的方式

  1. 使用无参构造创建对象,默认
  2. 使用有参构造创建对象有三种方式
    2.1. 下标赋值
     <!--有参构造方式1:通过下标给参数赋值-->
     <constructor-arg index="0" value="zhagnsanfeng"/>
    
    2.2 类型赋值
    <!--有参构造方式2:通过类型给参数赋值-->
    <!--<constructor-arg type="java.lang.String" value="zhangsan"/>-->
    
    2.3 直接通过参数名赋值
      <!--有参构造方式3:直接通过参数名赋值-->
      <constructor-arg name="name" value="zhangsanfeng"/>
    

总结:在配置文件加载的时候,Spring容器中管理的对象就已经被初始化了。默认是单例实现,无论get多少次都只初始化了一次。

5. 配置

5.1 别名

<!--别名,如果添加了别名,我们也可以使用别名获取对象-->
<alias name="user" alias="userNew"/>
   User user = (User) context.getBean("user");
   //User user = (User) context.getBean("userNew");

5.2 Bean的配置

  <!--
    id:bean的唯一标识
    class:bean对象所对应的全限定名:包名+类名
    name:也是别名,而且可以逗号分隔取多个别名
    -->
    <bean id="user" class="com.kuang.pojo.User" name="user2">

5.3 imort

这个import,一般用于团队开发,它可以将多个配置文件导入合并为一个。
比如将多个xml导入到一个总的applicationContext.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">

    <import resource="beans.xml"/>
    <import resource="beans2.xml"/>
</beans>

6. DI(Dependency Injection)依赖注入

依赖注入是控制反转的一种实现方式

6.1 构造注入

前面说过了

6.2 set方式注入【常用】

  • 依赖注入:set注入
    • 依赖:bean对象的创建依赖于spring容器
    • 注入:bean对象中的所有属性,由容器来注入
  • 各种类型的注入方式

Address类

package com.kuang.pojo;

public class Address {
    private  String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Address{" +
                "address='" + address + '\'' +
                '}';
    }
}

Student类

package com.kuang.pojo;

import java.util.*;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String[] getBooks() {
        return books;
    }

    public void setBooks(String[] books) {
        this.books = books;
    }

    public List<String> getHobbys() {
        return hobbys;
    }

    public void setHobbys(List<String> hobbys) {
        this.hobbys = hobbys;
    }

    public Map<String, String> getCard() {
        return card;
    }

    public void setCard(Map<String, String> card) {
        this.card = card;
    }

    public Set<String> getGames() {
        return games;
    }

    public void setGames(Set<String> games) {
        this.games = games;
    }

    public Properties getInfo() {
        return info;
    }

    public void setInfo(Properties info) {
        this.info = info;
    }

    public String getWife() {
        return wife;
    }

    public void setWife(String wife) {
        this.wife = wife;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", address=" + address +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", card=" + card +
                ", games=" + games +
                ", info=" + info +
                ", wife='" + wife + '\'' +
                '}';
    }
}

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">
    <bean id="address" class="com.kuang.pojo.Address">
        <property name="address" value="北京"/>
    </bean>

    <bean id="student" class="com.kuang.pojo.Student">
        <!--普通值注入,直接给value赋值-->
        <property name="name" value="张三"/>
        <!--类变量注入:ref引入Bean-->
        <property name="address" ref="address"/>
        <!--数组注入-->
        <property name="books">
            <array>
                <value>JAVA实战</value>
                <value>Python入门</value>
                <value>深入理解Nginx</value>
            </array>
        </property>
        <!--list注入-->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>打游戏</value>
            </list>
        </property>
        <!--map注入-->
        <property name="card">
            <map>
                <entry key="身份证" value="456987451257895461"/>
                <entry key="银行卡" value="62254802548115"/>
            </map>
        </property>
        <!--set注入-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>CF</value>
            </set>
        </property>
        <!--null注入-->
        <property name="wife">
           <null/>
        </property>
        <!--Properties注入-->
        <property name="info">
            <props>
                <prop key="学号">200510</prop>
                <prop key="性别"></prop>
            </props>
        </property>
    </bean>
</beans>

测试类

import com.kuang.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student)context.getBean("student");
        System.out.println(student);
    }
}

打印结果

Student{name='张三', address=Address{address='北京'}, books=[JAVA实战, Python入门, 深入理解Nginx], hobbys=[听歌, 打游戏], card={身份证=456987451257895461, 银行卡=62254802548115}, games=[LOL, CF], info={学号=200510, 性别=}, wife='null'}

6.3 其它方式

6.3.1 p命名空间注入

需要导入p命名空间xml约束,其实就是对应的set注入,只不过写法不一样。
在这里插入图片描述
测试类
在这里插入图片描述

6.3.2 c命名空间注入

必须要有有参构造,需要导入c命名空间xml约束,其实就是对应的构造方法注入,只不过写法不一样。
在这里插入图片描述

测试类
在这里插入图片描述

6.4 Bean作用域

在这里插入图片描述

6.4.1 单例模式【默认】

原型模式:scope=“singleton”。默认就是单例模式,无论从容器中获取多少次都只有一个实例。
在这里插入图片描述

<bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="李四" />
  <bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="李四" scope="singleton" />

以上两段代码是相同的。
在这里插入图片描述

6.4.2 原型模式

在这里插入图片描述
原型模式:scope=“prototype”。每次从容器中获取的时候都会产生一个新对象。

    <!--通过构造器注入:construct-args-->
    <bean id="user2" class="com.kuang.pojo.User" c:age="18" c:name="李四" scope="prototype" />

在这里插入图片描述

6.4.3 其他模式

  • request
  • session
  • application

以上模式只能在web开发中使用。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值