Spring 学习笔记

本文详细介绍了Spring框架中的IOC(控制反转)和AOP(面向切面编程)概念,包括IOC的推导、本质、配置、依赖注入(DI)的多种方式以及Bean的作用域。此外,还讲解了Spring的AOP使用,如切面的定义和实现方式,以及Mybatis与Spring的集成,探讨了事务管理的重要性。通过实例和代码示例,帮助读者深入理解Spring框架的核心功能。
摘要由CSDN通过智能技术生成

Spring

为什么需要Spring?想想我之前自己写的五子棋项目,其中有个棋盘对象是十分的恼人,这个对象诗歌单例,在服务层要调用,在表示层要调用,每次都要为其在类中设置一个成员变量,但是有了Spring以后,因为Spring是默认单例(也可以设置不是单例),就可以通过 xxx.getBean()的方法,获得这个单例了。其实,Spring的作用和Session有部分相似。

Spring最重要的部分是 IOC(控制反转)AOP(面向切面编程),本文还会对Spring配置做精简版的介绍

Spring在用户获取实例的时候,是一次性将所有配置的Bean都实例化的(但是prototype的不是),然后根据用户要求获取,比如说我的配置文件里有一大堆的bean:

image-20210224000301741

其中的UserServiceImpl中的无参构造和set方法我都添加了输出:

image-20210224000357739

但是我的测试类在获取其他bean的时候,任然会触发输出,说明其他不用的bean也被实例化了:

image-20210224000539320

IOC

IOC的推导

IoC基础

新建一个空白的maven项目

分析实现

我们先用我们原来的方式写一段代码 .

1、先写一个UserDao接口

public interface UserDao {
   
   public void getUser();
}

2、再去写Dao的实现类

public class UserDaoImpl implements UserDao {
   
   @Override
   public void getUser() {
   
       System.out.println("获取用户数据");
  }
}

3、然后去写UserService的接口

public interface UserService {
   
   public void getUser();
}

4、最后写Service的实现类

public class UserServiceImpl implements UserService {
   
   private UserDao userDao = new UserDaoImpl();

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

5、测试一下

@Test
public void test(){
   
   UserService service = new UserServiceImpl();
   service.getUser();
}

这是我们原来的方式 , 开始大家也都是这么去写的对吧 . 那我们现在修改一下 .

把Userdao的实现类增加一个 .

public class UserDaoMySqlImpl implements UserDao {
   
   @Override
   public void getUser() {
   
       System.out.println("MySql获取用户数据");
  }
}

紧接着我们要去使用MySql的话 , 我们就需要去service实现类里面修改对应的实现

public class UserServiceImpl implements UserService {
   
   private UserDao userDao = new UserDaoMySqlImpl();

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

在假设, 我们再增加一个Userdao的实现类 .

public class UserDaoOracleImpl implements UserDao {
   
   @Override
   public void getUser() {
   
       System.out.println("Oracle获取用户数据");
  }
}

那么我们要使用Oracle , 又需要去service实现类里面修改对应的实现 . 假设我们的这种需求非常大 , 这种方式就根本不适用了, 甚至反人类对吧 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性太高了, 牵一发而动全身 .

那我们如何去解决呢 ?

我们可以在需要用到他的地方 , 不去实现它 , 而是留出一个接口 , 利用set , 我们去代码里修改下 .

public class UserServiceImpl implements UserService {
   
   private UserDao userDao;
// 利用set实现
   public void setUserDao(UserDao userDao) {
   
       this.userDao = userDao;
  }

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

现在去我们的测试类里 , 进行测试 ;

@Test
public void test(){
   
   UserServiceImpl service = new UserServiceImpl();
   service.setUserDao( new UserDaoMySqlImpl() );
   service.getUser();
   //那我们现在又想用Oracle去实现呢
   service.setUserDao( new UserDaoOracleImpl() );
   service.getUser();
}

大家发现了区别没有 ? 可能很多人说没啥区别 . 但是同学们 , 他们已经发生了根本性的变化 , 很多地方都不一样了 . 仔细去思考一下 , 以前所有东西都是由程序去进行控制创建 , 而现在是由我们自行控制创建对象 , 把主动权交给了调用者 . 程序不用去管怎么创建,怎么实现了 . 它只负责提供一个接口 .

这种思想 , 从本质上解决了问题 , 我们程序员不再去管理对象的创建了 , 更多的去关注业务的实现 . 耦合性大大降低 . 这也就是IOC的原型 !

IOC本质

IoC和DI

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

Spring对对象的控制方式

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

XML配置和注解配置的区别

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

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

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

第一个Spring程序

  1. 导入Maven依赖
 <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>

    </dependencies>
  1. 编写实体类
public class User {
   
    private int id;
    private String name;
    private String address;
  //constructor 
  //get set
}
  1. 编写Spring配置文件

一般情况下,这个配置文件要命名为 applicationContext.xml,这里我们简单命名为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
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="User" class="top.faroz.pojo.User">
        <property name="name" value="FARO_Z"/>
        <property name="id" value="123"/>
        <property name="address" value="KKK_Street"/>
    </bean>

</beans>
  1. 测试
		@Test
    public void constructUserTest() {
   
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("User");
        System.out.println(user);
    }

image-20210223143822280

通过Spting创建的对象默认是单例的,当然也可以自己修改,这在后面Spring属性部分会再提

Spring配置

别名

alias 设置别名 , 为bean设置别名 , 可以设置多个别名

<!--设置别名:在获取Bean的时候可以使用别名获取-->
<alias name="userT" alias="userNew"/>
  1. 为User设置一个别名kkk
<alias name="User" alias="kkk"/>
    
    <bean id="User" class="top.faroz.pojo.User">
        <property name="name" value="FARO_Z"/>
        <property name="id" value="123"/>
        <property name="address" value="KKK_Street"/>
    </bean>
  1. 测试类使用kkk来获取实例
  @Test
    void aliasTest() {
   
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Object kkk = context.getBean("kkk");
        System.out.println(kkk);
    }

image-20210223225326090

这个别名其实没什么🐦用,直接写name可以达到一样的效果

 <bean id="User" name="kkk" class="top.faroz.pojo.User">
        <property name="name" value="FARO_Z"/>
        <property name="id" value="123"/>
        <property name="address" value="KKK_Street"/>
    </bean>

Bean的配置

<!--bean就是java对象,由Spring创建和管理-->

<!--
   id 是bean的标识符,要唯一,如果没有配置id,name就是默认标识符
   如果配置id,又配置了name,那么name是别名
   name可以设置多个别名,可以用逗号,分号,空格隔开
   如果不配置id和name,可以根据applicationContext.getBean(.class)获取对象;

class是bean的全限定名=包名+类名
-->
<bean id="hello" name="hello2 h2,h3;h4" class="com.kuang.pojo.Hello">
   <property name="name" value="Spring"/>
</bean>

import

团队的合作通过import来实现 .

<import resource="{path}/beans.xml"/>

DI

Dependency Injection

概念

  • 依赖注入(Dependency Injection,DI)。
  • 依赖 : 指Bean对象的创建依赖于容器 . Bean对象的依赖资源 。
  • 注入 : 指Bean对象所依赖的资源 , 由容器来设置和装配 。

构造器注入

使用构造器注入,不需要set方法

使用无参构造器注入

1、User.java

public class User {
   

   private String name;

   public User() {
   
       System.out.println("user无参构造方法");
  }

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

   public void show(){
   
       System.out.println("name="+ name );
  }

}

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
       http://www.springframework.org/schema/beans/spring-beans.xsd">

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

</beans>

3、测试类

@Test
public void test(){
   
   ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
   //在执行getBean的时候, user已经创建好了 , 通过无参构造
   User user = (User) context.getBean("user");
   //调用对象的方法 .
   user.show();
}

结果可以发现,在调用show方法之前,User对象已经通过无参构造初始化了!

通过有参构造方法来创建

1、UserT . java

public class UserT {
   

   private String name;

   public UserT(String name) {
   
       this.name = name;
  }

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

   public void show(){
   
       System.out.println("name="+ name );
  }

}

2、beans.xml 有三种方式编写

<!-- 第一种根据index参数下标设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <!-- index指构造方法 , 下标从0开始 -->
   <constructor-arg index="0" value="kuangshen2"/>
</bean>
<!-- 第二种根据参数名字设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <!-- name指参数名 -->
   <constructor-arg name="name" value="kuangshen2"/>
</bean>
<!-- 第三种根据参数类型设置 -->
<bean id="userT" class="com.kuang.pojo.UserT">
   <constructor-arg type="java.lang.String" value="kuangshen2"/>
</bean>

3、测试

@Test
public void testT(){
   
   ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
   UserT user = (UserT) context.getBean("userT");
   user.show();
}

结论:在配置文件加载的时候。其中管理的对象都已经初始化了!

一般不使用构造器注入这种方式,一般使用的都是set注入的方式

Set注入(重点)

要求被注入的属性 , 必须有set方法 , set方法的方法名由set + 属性首字母大写 , 如果属性是boolean类型 , 没有set方法 , 是 is 。

测试类:

Address.java

 public class Address {
   
 
     private String address;
 
     public String getAddress() {
   
         return address;
    }
 
     public void setAddress(String address) {
   
         this.address = address;
    }
 }

Student.java

 package com.kuang.pojo;
 
 import java.util
Spring是一个开源的Java框架,用于构建企业级应用程序。它提供了一种轻量级的、非侵入式的开发方式,通过依赖注入和面向切面编程等特性,简化了Java应用程序的开发过程。 以下是关于Spring学习的一些笔记: 1. IoC(控制反转):Spring通过IoC容器管理对象的创建和依赖关系的注入。通过配置文件或注解,将对象的创建和依赖关系的维护交给Spring容器来管理,降低了组件之间的耦合度。 2. DI(依赖注入):Spring通过依赖注入将对象之间的依赖关系解耦。通过构造函数、Setter方法或注解,将依赖的对象注入到目标对象,使得对象之间的关系更加灵活和可维护。 3. AOP(面向切面编程):Spring提供了AOP的支持,可以将与业务逻辑无关的横切关注点(如日志、事务管理等)从业务逻辑分离出来,提高了代码的可重用性和可维护性。 4. MVC(模型-视图-控制器):Spring提供了一个MVC框架,用于构建Web应用程序。通过DispatcherServlet、Controller、ViewResolver等组件,实现了请求的分发和处理,将业务逻辑和视图展示进行了分离。 5. JDBC和ORM支持:Spring提供了对JDBC和ORM框架(如Hibernate、MyBatis)的集成支持,简化了数据库访问的操作,提高了开发效率。 6. 事务管理:Spring提供了对事务的支持,通过声明式事务管理和编程式事务管理,实现了对数据库事务的控制和管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FARO_Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值