跳转至

Spring框架

Spring官网

Spring各个模块

img

Spring优势

1、方便解耦

Student类,创建对象

Student s = new Student();

如果想要把Student改为Person

Person s = new Person();

如果有几十处的话,都需要修改,耦合性太大。

Java代码不再new创建对象,程序中用一个xml文件,里面配置对象名和类。使用反射,耦合性低。

IoC/DI

IoC(Inversion of Control)中文名称:控制反转,也被称为DI(dependency injection ):依赖注入。

创建对象的权利(控制的位置),由JAVA代码转移到spring容器,由spring的容器控制对象的创建,就是控制反转

由于控制反转概念比较含糊,所以又给出了一个新的名字:“依赖注入”,相对loC而言,“依赖注入”明确描述了“被注入对象依赖loC容器来配置依赖对象”,Dl是loC的别名。

IOCDI原理

IoC/DI 原理

如果每次创建对象的位置特别多,创建对象的代码和Java代码耦合性高,层和层之间的耦合性也高。所以把创建对象的代码交由Spring管理,不再在Java代码里创建对象。这就是IoC/DI。

在程序中会多一个配置文件applicationContext.xml,名字可以自己定义。

在xml中可以配置bean标签,例:<bean id="s" class="Student">,这行代码底层做的就是Student s = new Student();

构建是Spring底层通过反射技能做的。

构建的对象放到了Spring容器,底层是map集合。

applicationContext.xml通过反射创建对象,所有对象放在容器中,java程序从容器中取对象。

2、简化开发

对比MyBatis框架,定义接口、写映射文件,主要问题是解析mybatis.xml文件的代码,Spring就可以更简洁的处理。

3、AOP切面编程

不改变原有代码在它的基础上扩展。

4、声明式事务

5、整合各种优秀的框架

Spring是框架的框架。

不重复造轮子

A公司用a框架,B公司用b框架、C公司用c框架。3个框架的作用是完全一样的,用法也差不多。原有的技术加Spring的整合就可以很简单。不过后来Spring违背了这一原则,自己又出了新轮子。

第一个Spring项目-完成IoC/DI代码的实现

1、创建Maven项目,pom.xml添加依赖

在项目的pom.xml中添加Spring项目的最基本依赖。

Spring项目想要运行起来必须包含:

  • spring-context.jar - 依赖spring-corespring-aopspring-expressionspring-beans四个jar。

  • spring-core.jar - 依赖spring-jcl.jar

  • spring-aop.jar

  • spring-expression.jar

  • spring-beans.jar

  • spring-jcl.jar

所以在Maven中想要使用Spring框架只需要在项目中导入spring-context就可以了,其他的jar包根据Maven依赖传递性都可以导入进来。

pom.xml

2、实体类

3、Spring配置文件

在src/main/resources下新建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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- com.hh.pojo包下component的注解都会扫描到-->
    <!--    <context:component-scan base-package="com.hh.pojo"></context:component-scan>-->

    <!--    setter方法 给属性赋值。下面的id和name都是setter方法中的名字(并非属性名)-->
    <bean id="b" class="com.hh.pojo.Book">
        <property name="id" value="1"></property>
        <property name="name" value="项目驱动零起点学Java"></property>
    </bean>

    <!--    类构造器 给属性赋值。下面的id和name都是构造器方法中的参数名字(并非属性名)-->
    <bean id="b2" class="com.hh.pojo.Book">
        <constructor-arg name="id" value="2"></constructor-arg>
        <constructor-arg name="name" value="红高粱"></constructor-arg>
    </bean>

    <!--    创建对象-->
    <bean id="boy" class="com.hh.pojo.Boy">
        <property name="age" value="22"></property>
        <property name="name" value="小明"></property>
    </bean>
    <bean id="girl" class="com.hh.pojo.Girl">
        <property name="age" value="19"></property>
        <property name="name" value="露露"></property>
        <property name="boyfriend" ref="boy"></property>
    </bean>

</beans>

4、创建容器

在测试类中创建容器

package com.msb.test;

import com.msb.pojo.Book;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        //创建Spring容器:
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //获取对象:
        //Book book = (Book)context.getBean("b");
        Book book = (Book)context.getBean("b2");
        //打印对象的信息:
        System.out.println(book.getName() + "---" + book.getId());
    }
}

属性注入

以前:setter方式

Book b = new Book(); 
b.setId(1); 
b.setName("项目驱动零起点学Java")

现在:属性注入-设置注入

<bean id="b" class="com.msb.pojo.Book">
    <property name="id1" value="1" ></property> <!--name不是属性的名字,是set方法的名字-->
    <property name="name1" value="项目驱动零起点学Java"></property>
</bean>

以前:构造器方式

Book b = new Book(1"项目驱动零起点学Java"); 

现在:属性注入-构造注入

<bean id="b2" class="com.msb.pojo.Book">
    <constructor-arg name="id2" value="2"></constructor-arg>
    <constructor-arg name="name2" value="红高粱"></constructor-arg>
</bean>

属性为引用数据类型

类的属性可以是基本数据类型,也可以是引用数据类型。

设置属性的值:

  • value:简单数据类型(基本数据类型+String)直接设置。

  • ref:需要引用另一个bean的id。也就是说这个参数是一个类类型,且这个类的对象也被Spring容器管理。

IoC/DI相关的注解

上面<bean>标签是创建对象,可以通过注解简化。

注解名称 解释
@Component 实例化Bean, 默认名称为类名首字母变小写
@Repository 作用和@Component一样。用在持久层
@Service 作用和@Component一样。用在业务层
@Controller 作用和@Component一样。用在控制器层
@Configuration 作用和@Component一样。用在配置类上
@Autowired 自动注入。默认byType,如果多个同类型bean,使用byName
@ Value 给普通数据类型属性赋值

前五个注解作用都是创建对象。只所以搞出这么多,就是在语义上给你区别,不同层用不同的注解。

@Component

在要创建对象的类中加入@Component注解,会自动构建这个类的对象,对象名字默认为:类名首字母变小写。

注解在哪个package包下?要想找到这些注解,需要将注解所在的包进行扫描:设置需要扫描的包。并且需要在applicationContext.xml中添加context命名空间

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"     xmlns:context="http://www.springframework.org/schema/context"     xsi:schemaLocation="http://www.springframework.org/schema/beans     https://www.springframework.org/schema/beans/spring-beans.xsd     http://www.springframework.org/schema/context     https://www.springframework.org/schema/context/spring-context.xsd"> 

    <context:component-scan base-package="com.msb.service"></context:component-scan> 

</beans>

属性注入的注解

@Value的使用

给普通数据类型赋值的注解,普通数据类型包括:八种基本数据类型+String,并且不需要依赖set方法。

@Autowired的使用

添加@Autowired注解后会把容器中的对象自动注入进来,并且不需要依赖set方法。