Spring入门知识以及项目搭建与依赖注入

Spring基础知识了解

Spring官网:https://spring.io/

什么是Spring?

Spring是与2003年新奇的一个轻量级的java开发框架,它是为了解决企业引用开发的复杂新二创建的。Spring的核心是控制反转(IOC)和面向切面编程(AOP)

Spring的主要作用是为代码“解耦”,降低代码间的耦合度。就是让对象和对象、模块和模块之间不是使用代码关联,而是通过配置来说明。即在Spring中说明对象或者模块的关系。

Spring根据代码的功能特点,使用IOC降低业务之间耦合度。IOC是的主业务在相互调用过程中,不用自己维护关系了,即不用自己创建需要使用的对象了。而是由Spring容器统一管理,自动“注入”,即就是自动赋值。使用AOP使得系统级服务得到最大的复用,且不用再由程序员手动将系统服务“混杂”到主业务逻辑中了,而是有Spring容器统一完成。

总之:Spring是一个容器,它是整合其他框架的框架,它的核心是IOC和AOP,它是由20多个模块组成。

耦合度:事物之间的关联程度。比如一块布耦合度非常高,用这块布做的衣服,耦合度就相对低一点。

Spring的特点

  1. 轻量级。由20多个模块构成,每个jar包都很小,核心包就3M左右
  2. 面向接口编程。使用接口,项目的可维护性,可扩展性都高。接口不关心实现类的类型,使用接口指向实现类,切换实现类即可换整个功能。
  3. AOP:面向切面编程。三层式开发:界面层、业务逻辑层、数据访问层会有公共的逻辑或者业务处理,重复的代码,我们会提出来单独写,谁用谁取。那些公共的代码就是切面。公共的提取出来,需要的时候反置回去,就是面向切面编程,底层的原理是动态代理。
  4. 整合其他框架。整合后使其他框架更易用。

Spring的体系结构

在这里插入图片描述

Data Access(数据库整合):

JDBC, ORM, OXM, JMS, Transaction

Web(MVC Web 开发):

Web, Servlet, Portlet, Struts

AOP(切面编程)

AOP 框架: Aspects

JVM的代理:Instrumentation;

发送消息:Messaging;

Core Container(核心容器):

Beans: 管理 Beans

Core: Spring 核心

Context: 配置文件

ExpressionLanguage: SpEL 表达式

Test(Junit 整合)

什么是IOC?

控制反转IOC(Inversion of Control)是一种思想。由于Spring容器进行对象的创建和依赖注入。程序员取出直接使用。

正转:由程序员创建对象和依赖注入称为正转。

Student student = new Student();
student.setName("张三");

反转:由Spring容器创建对象和依赖注入称为反转,将控制权从程序员手中夺走。

<bean id="student" class="com.www.spring.demo.Student">
        <property name="id" value="100"/>
        <property name="account" value="张三"/>
    </bean>

项目搭建

  1. 搭建项目
  2. 更改pom.xml文件。添加spring核心依赖
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.2.RELEASE</version>
</dependency>
  1. 创建实体类。
public class Admin {
    private Integer id;
    private String name;
    private String num;
    private String account;

    public Admin(Integer id, String name, String num) {
        this.id = id;
        this.name = name;
        this.num = num;
    }

    public Admin() {
    }

    public void doSome() {
        System.out.println("执行此方法");
    }
}
  1. 添加applicationContext.xml文件,用于创建对象。
  2. 在applicationContext.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">

    <!--告诉spring创建对象
        声明bean , 就是告诉spring要创建某个类的对象,一个bean只能声明一个对象
        id:对象的定义名称,惟一的.spring通过这个id找到对象
        class:类的全限定名称(不能是接口,因为spring是反射机制创建对象的)
		scope:bean的作用域
               singleton(默认):单例的只创建一个对象,在spring启动时就会创建好
               prototype:原型的 ,每次都会创建一个对象,在获取时才创建

        spring框架有一个map集合存放对象
        springMap.put(id值,对象)
    -->
    <bean id="admin" class="com.www.spring.modle.Admin"/>
</beans>
<!--
spring 的配置标签
1.beans: 跟标签,spring吧java对象称为bean
2.spring-beans.xsd是约束文件,和Mybatis指定 dtd是一样的 用来控制文件中出现的标签.

-->
  1. 测试
public void test1(){
        //使用Spring容器创建的对象  默认调用无参构造
        //1.指定spring配置文件的名称
        String config = "applicationContext.xml";
        //2.创建表示spring容器的对象  ApplicationContext
        //ApplicationContext 表示spring的容器
        //ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);//此时构造方法执行,创建对象
    //在创建spring对象时会创建配置文件中所有的对象

        //从容器中获取某个对象,要调用对象的方法
        //getBean("配置文件中的bean的id值")
        Admin admin = (Admin) ac.getBean("admin");

        admin.doSome();
    }

以上创建对象的过程虽然看起来过程复杂,且漫长,但是有没有发现此过程中我们是没有new过的,直接通过配置文件以及名字就创建对象了。

spring中常用到的方法

    public void test2(){
        String config = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        //getBeanDefinitionCount():容器中定义的对象的个数
        int nums = ac.getBeanDefinitionCount();
        System.out.println("容器中定义的对象的个数"+nums);
        //getBeanDefinitionNames():容器中定义的每个对象的名字
        String names[] = ac.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }

创建非自定的对象:

<bean id="mydate" class="java.util.Date"/>
<!--
只要知道全类名就好了
-->

依赖注入(di)

di:创建对象并给属性赋值。

两种实现方法:

  1. 在spring的配置文件中,使用标签和属性完成,叫做基于XML的di实现
  2. 使用spring中的注解,完成属性赋值,叫做基于注解的di实现

基于XML的di

  1. set注入(设值注入):spring调用类的set方法,在set方法可以实现属性的赋值。
<!--
简单类型的注入 value
-->
<bean id="student" class="com.www.spring.modle.Student">
        <property name="name" value="张三"/>
        <property name="id" value="1"/>
        <property name="num" value="1001"/>
</bean>
 <!--
引用类型的注入 ref
-->
<bean id="student1" class="com.www.spring.modle.Student">
    <property name="name" value="张四"/>
    <property name="id" value="2"/>
    <property name="num" value="1002"/>
    <property name="admin" ref="admin"/>
</bean>
<bean id="admin" class="com.www.spring.modle.Admin">
    <property name="name" value="admin"/>
    <property name="id" value="1"/>
</bean>
<!--
set注入时,调用实体类中的set方法
-->
  1. 构造注入,spring调用类的有参构造方法,创建对象,在构造方法中完成赋值。

使用constructor-arg标签
一个constructor-arg标签表示构造方法的一个参数
name:属性表示构造方法的形参名
index:表示构造方法的参数的位置,从左往右 0 1 2 3…
ref:构造方法的形参是引用类型
value:构造方法的形参是简单类型

   <!--使用name方式-->
    <bean id="student2" class="com.www.spring.modle.Student">
        <constructor-arg name="name" value="张武"></constructor-arg>
        <constructor-arg name="num" value="1003"></constructor-arg>
        <constructor-arg name="admin" ref="admin"></constructor-arg>
    </bean>
    <!--使用index方式 -->
    <bean id="student3" class="com.www.spring.modle.Student">
        <constructor-arg index="1" value="1004"></constructor-arg>
        <constructor-arg index="0" value="张流"></constructor-arg>
        <constructor-arg index="2" ref="admin"></constructor-arg>
    </bean>
    <!--省略index的方式-->
    <bean id="student4" class="com.www.spring.modle.Student">
        <constructor-arg  value="张流"></constructor-arg>
        <constructor-arg  value="1004"></constructor-arg>
        <constructor-arg  ref="admin"></constructor-arg>
    </bean>
引用类型的自动注入

引用类型的自动注入:Spring框架根据某些规则给引用类型赋值。不用自己给引用类型赋值使用的规则常用的是byName,byType。

byName(按名称注入)
  1. byName(按名称注入):java类中引用类型的属性名和spring容器中(配置文件中)bean的id名称一样,且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型。
    <bean id="student5" class="com.www.spring.modle.Student" autowire="byName">
        <property name="name" value="张其"/>
        <property name="id" value="7"/>
        <property name="num" value="1007"/>
    </bean>
byType(按类型注入)

2.byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)bean的class属性是同源关系的,这样的bean可以赋值给引用类型
同源的意思

  1. java类中引用类型的数据类型和bean的class的值是一样的
  2. java类中引用类型的数据类型和bean的class的值是父子类关系的。
  3. java类中引用类型的数据类型和bean的class的值是接口和实现类的关系

注 : byType中, 在xml中声明的bean只能有有一个符合条件的

 <bean id="student6" class="com.www.spring.modle.Student" autowire="byName">
        <property name="name" value="张其"/>
        <property name="id" value="7"/>
        <property name="num" value="1007"/>
</bean>
使用多配制文件

当类的声明非常多的时候,将所有的声明都放在一个配置文件中是不可取的;在做项目的时候,多人使用同一个配置文件时,是及其容易出现错误的;

多配制文件的优势

  1. 每个文件的大小比一个文件小得多,易操作,效率高。
  2. 避免多人竞争带来的冲突。

多文件的分配方式

  1. 如果项目由多个模块构成,建议一个模块一个配置文件。
  2. 按类的功能,数据库相关配置一个文件,做事务的功能一个配置文件,做service功能一个配置文件。

具体操作

<!--student配置文件-->
    <bean id="student" class="com.www.spring.modle.Student" autowire="byType">
        <property name="name" value="张其"/>
        <property name="id" value="7"/>
        <property name="num" value="1007"/>
    </bean>
 <!--admin配置文件-->
    <bean id="admin" class="com.www.spring.modle.Admin">
        <property name="name" value="admin"/>
        <property name="id" value="1"/>
    </bean>
<!--主配置文件-->
    <!--
       关键字classpath:表示类路径(class文件所在的目录),
                        在spring的配置文件中要指定其他文件的位置,需要使用classpath,
                        告诉spring到哪去加载读取文件。
注意:classpath后面不要随意添加空格,容易出现错误
    -->
    <import resource="classpath:be01/spring-Student.xml"/>
    <import resource="classpath:be01/spring-Admin.xml"/>
public void test4(){
    //加载总文件
        String config = "be01/spring-Total.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(config);
        Student student = ac.getBean("student",Student.class);
        System.out.println(student);
    }

以上主配置文件中import可以使用通配符

<!--
    使用通配符时,注意文件需要在一级(如:be01)目录下,否则将不能加载到主文件;
还有主配置文件的名字不能与其他问价前缀相同。
    -->
    <import resource="classpath:be01/spring-*.xml"/>

基于注解的di

使用注解的步骤:
  1. 加入maven的依赖;早在加入spring-context时就已经间接加入了spring-aop,所以不需要再添加。
  2. 在类中加入spring的注解;
  3. 在spring的配置文件中,加入一个组件扫描的标签,说明注解的位置。
<context:component-scan base-package="com.www.spring"/>

添加完component-scan标签后配置文件会多出:

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
  1. 使用注解
常用的注解:
  1. @component:创建对象的,相当于bean标签的功能,属性value就是对象的名称,也就是bean中的id值,value的值时惟一的,创建的对象在整个spring容器中是惟一的,创建对象时调用构造方法,注解的位置:类的上面。
//写法1:
//@component(value = “admin)
//等同于<bean id="admin" class="com.ffyc.spring.modle.Admin"></bean>

//写法2:省略value
//@component(指定对象的名称)

//写法3:不指定对象的名称,由spring默认名称:首字母小写的类名。
//@component


@Component(value = "admin")//等同于<bean id="admin" class="com.ffyc.spring.modle.Admin"></bean>
public class Admin {
    private Integer id;
    private String name;
    private String num;
    private String account;

    public Admin(String name, String num, String account) {
        this.name = name;
        this.num = num;
        this.account = account;
    }


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public String getNum() {
        return num;
    }

    public void setNum(String num) {
        this.num = num;
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public Admin(Integer id, String name, String num) {
        this.id = id;
        this.name = name;
        this.num = num;
    }

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

    public void doSome() {
        System.out.println("执行此方法");
    }

    @Override
    public String toString() {
        return "Admin{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", num='" + num + '\'' +
                ", account='" + account + '\'' +
                '}';
    }
}

  1. @Respotory:(用在持久层上面的)与@component功能一致,创建的是dao对象,dao对象是能访问数据库的。

  2. @service:(用在业务逻辑层类上面的) 与@component功能一致,放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务功能的。

  3. @controller:(用在控制器上面的)与@component功能一致,放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求结果。

以上注解与@component功能一致,语法相同,但是各自还有额外功能,他们是给项目分层的。

  1. @value:为简单类型赋值,使用此注解时,必须已经创建对象
/*
       可以写在属性定义的上面,无需set方法,比较常用
       也可以写在set方法上面
     */

@Component("student")
@Data
public class Student {
    private Integer id;
    @Value( "张吧")
    private  String name;
    @Value(value = "1008")
    private String num;

    private Admin admin;

    public Student() {
    }

    public Student(String name, String num, Admin admin) {
        this.name = name;
        this.num = num;
        this.admin = admin;
    }
}

  1. @Autowired:spring框架提供的注解,实现引用类型的赋值。spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byType,byName。默认使用byTy自动注入。
 @Autowired
private Admin admin;

如果使用byName的方式:需要借助@Qualifier(value = “对象名称”)

	@Autowired
    @Qualifier(value = "admin")//这里的admin是Admin类创建对象的名称,相当于bean的id
    private Admin admin;//这里的admin是Student类中属性名
//两个注解不分先后

@Autowired中有一个属性:required

required=true :表示引用类型赋值失败,程序终止,程序报错

required=false:表示引用类型赋值失败,程序不终止,引用类型为null

  1. @Resource:来之jdk中的注解,spring提供了jdk中@Resource注解的支持,该注解可以支持byType、byName方式,默认是byName。

先使用byName自动注入,如果byName赋值失败,再改用byType自动注入。

只想使用byName一种方式时:

@Resource(name = "admin")
    private Admin admin;

注解与xml配置文件对比

配置文件:

优点:代码和值是完全分开的,对于经常改值的,可以用配置文件;

缺点:语法繁杂,与代码完全分开,浏览源代码时,不知道对应的值。

注解:

优点:快捷方便,速度快,代码简洁;不经常改变的用注解比较方便

缺点:硬编入java代码中,修改后需要重新编译

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值