分享

​Spring基础入门

 夜猫速读 2022-05-05 发布于湖北

Spring Famework

Spring 框架:由Spring组织提供的开源软件框架,利用这套框架可以大大简化软件的开发过程,Spring采用一定规范约定框架的使用,来简化开发。使用时候必须准守这些规范。

框架:软件的半成品。利用框架编写软件可以大大简化开发过程。

Spring 框架核心功能:

  • IoC/DI:控制反转和依赖注入

  • AOP:面向“切面(儿)”编程

    • 在后续 稻草问答 项目中详细讲解

IoC 控制反转

  1. 主动控制:由应用程序代码,主动控制对象的创建,使用和销毁。

  2. 控制反转:是指对象的创建和销毁的控制权交给当前和环境(Spring),程序通过环境(Spring)拿到对象,使用对象。

一个控制反转例子:

  • 李老板:控制斧子对象的创建和管理

  • 光头强:从李老板手里拿到斧子去使用

    • 对于光头强来说,不用关心斧子的创建和管理,只需要使用斧子即可。

Spring案例:

  • Spring 框架,负责创建和管理对象

  • 应用程序,从框架中获取对象,使用对象

    • 对于应用来说简化了开发(不用管理对象)

下面的案例中,我们使用Spring管理简单对象,貌似繁琐,在日后才能体现其强大功能。

Spring HelloWorld

案例目的:验证Spring IoC 可以实现对象的管理。

  1. 利用Maven导入Spring框架

<properties>  <!-- 设置 JDK 版本为 1.8 -->  <maven.compiler.target>1.8</maven.compiler.target>  <maven.compiler.source>1.8</maven.compiler.source>  <!-- 设置编码为 UTF-8 -->  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>  <maven.compiler.encoding>UTF-8</maven.compiler.encoding></properties>
<dependencies> <!-- Spring Context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.2.RELEASE</version> </dependency> <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency></dependencies>

创建一个类--镰刀:heimao包下建立

/** * 镰刀类 */public class Axe {    /**     * 输出对象时候自动调用的方法。     * @return     */    @Override    public String toString() {        return "Hello World!Axe!";    }}
  1. 创建一个配置类,告诉Spring如何管理斧子对象创建一个config包在包下面创建一个Config类

/** * Spring 的配置类 * 用于约定Spring管理的对象 * @Configuration Spring提供的注解,标注了@Configuration注解的 * 类,作为Spring的配置类! */@Configurationpublic class Config {    /**     * @Bean 是Spring提供的注解,标注在方法上,方法的返回值就是     * Spring管理的对象。Spring 的内部就有了一个Axe类型的对象。     */    @Bean    public Axe axe(){       return new Axe();    }}
  1. 初始化Spring,从Spring中获取创建好的斧子对象

  2. 验证斧子对象,如果证明有斧子对象,就说明Spring可以创建管理对象。tedu包下新建demo1类

public class Demo01 {    public static void main(String[] args) {        /**         * 初始化Spring:Spring就会根据配置类,创建Axe         * - AnnotationConfigApplicationContext 就是Spring!         *   Annotation 注解         *   Config 配置         *   Application 应用程序         *   Context 上下文         * - 创建对象的参数是Spring的配置类!!!         *   由于配置类中声明了 Axe 类型的对象,所以Spring中就管理了Axe对象         */        AnnotationConfigApplicationContext ctx =                new AnnotationConfigApplicationContext(Config.class);        /**         * Spring 提供了获取对象的方法 getBean(类型)         * 如果能够在Spring中找到对应类型的对象,就得到对象         * 如果找不到就会出现异常:NoSuchBeanDefinitionException         */        Axe axe = ctx.getBean(Axe.class);        System.out.println(axe);        //测试找不到的情况,如下代码将出现异常NoSuchBeanDefinitionException        Object obj = ctx.getBean(Date.class);        System.out.println(obj);    }}

JUnit

JUnit是开一的Java单元测试工具。用于软件组件单元测试。

使用步骤:

  1. 利用Maven导入JUnit

<dependency>    <groupId>junit</groupId>    <artifactId>junit</artifactId>    <version>4.13</version></dependency>

2.创建测试案例,测试案例需要标注 @Test注解

public class TestCase {    /**     * 编写测试案例方法:     * - 标注@Test方法     * - 当前类必须是公有类     * - 测试方法必须是 公有 无参数 无返回值 的方法     * - 方法名随意!     */    @Test    public void hello(){        //编写软件的测试过程 ...        System.out.println("Hello World!");    }}

3.执行测试案例

使用JUnit测试Spring :创建一个axeTest

//使用Junit 测试Spring?@Testpublic void axeTest(){    //初始化Spring    AnnotationConfigApplicationContext ctx=            new AnnotationConfigApplicationContext(Config.class);    //从Spring中获取被管理的对象    Axe axe = ctx.getBean(Axe.class);    //测试    System.out.println(axe);}

Spring IoC 的工作原理

  • Spring 负责创建管理对象

  • Java程序可以从Spring中获得对象,使用对象

Java Bean

Bean: 豆子

Java 豆子:按照一定规范编写的Java对象,这些对象具有类似的编码风格,有些象咖啡豆,每个都不同,但是都非常相似。

Java Bean 规范:行业中编写Java类的通行规范,几乎所有企业采用!

  • 需要定义包(package),方便使用反射API

  • 需要定义无参数构造器,可以利用默认构造器,方便派生子类

  • 实现序列化接口,方便使用缓存

  • 使用get/set方法访问对象属性,称为Bean属性,可以利用反射等动态特性

Spring 建议:被Spring IoC 管理的对象,要按照Java Bean规范定义!Spring 基于这个规则,将Spring IoC管理的对象称为“JavaBean对象”。

如:ctx.getBean() 方法的意义,就是从Spring IoC中获取一个创建好的的JavaBean对象。

Spring 建议使用JavaBean规范,但是Spring也宽泛支持任何的Java对象。

package cn.heimao;import java.io.Serializable;/** * Worker: 工人 * 符合JavaBean规则的类型! */public class Worker implements Serializable {    private String name = "光头强";    public Worker(){    }    public Worker(String name){        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

Spring BeanID

Spring IoC中创建JavaBean对象时候,为每个JavaBean对象指定了唯一的ID,相当于对象的名字。当对象类型有冲突的情况下,就可以使用对象名字来得到对象。

  • 按照类型获取对象时候,如果Spring中有两个类型相的对象,就会出现异常:No qualifying bean of type 'cn.tedu.Axe' available: expected single matching bean but found 2: axe,axe2。意思是没有找到唯一的Aex类型Bean对象,实际上找到了两个类型相同Bean对象!

  • 如果有类型相同的Bean对象时候,就需要使用BeanID获取对象,解决冲突。

    • @Bean注解标注的方法名,就是Bean对象的ID

案例获取BeanID:

  1. 声明多个类型相同的Bean在Config类中进行编写

@Bean// Bean ID axepublic Axe axe(){   return new Axe();}
// 在Spring中创建了两个类型是Axe的对象@Bean// Bean ID axe2public Axe axe2(){ return new Axe();}

2.在测试类中编写如下代码删除原先的Bean对象测试

@Test    public void beanID(){            AnnotationConfigApplicationContext ctx=new                    AnnotationConfigApplicationContext(Config.class);            //按照BeanID在Spring中查找相同的Bean对象         Axe axe=ctx.getBean("axe2",Axe.class);         System.out.println(axe);     }

3.输出同类型的全部BeanID编写测试用例

//getBeanNamesForType 获取某个类型的全部Bean IDString[] names = ctx.getBeanNamesForType(Axe.class);//输出全部的BeanIDSystem.out.println(Arrays.toString(names));

4.案例利用BeanID获取指定的Bean编写测试用例

Axe axe = ctx.getBean("axe2",Axe.class);System.out.println(axe);

JUnit 的 @Before @After

Before: 在...之前

After:在...之后

JUnit提供了测试案例生命周期注解,用于优化测试案例:

  • @Before 注解标注的方法,在测试案例之前执行。

    • 用于初始化案例中需要使用的资源,比如Spring容器,数据库连接池等

  • @After 标注的方法,在测试案例执行之后执行。

    • 用于回收测试案例中使用的资源,比如关闭Spring,关闭数据库连接池等

优点:不要每个测试案例都重新初始化资源。

在测试案例中利用@Before @After 封装创建Spring和回收Spring的代码,后续的案例就无需再创建Spring对象了!大大简化了测试案例的编写。

案例

AnnotationConfigApplicationContext ctx;@Beforepublic void init(){    System.out.println("在测试案例之前");    ctx = new AnnotationConfigApplicationContext(Config.class);}
@After //destroy 销毁public void destroy(){ System.out.println("在测试案例之后"); //关闭一下Spring, 回收Spring的资源 ctx.close();}

测试案例(不用再次初始化Spring):

@Testpublic void beanID(){    /*     * 按照BeanID在Spring中查找ID相同的Bean对象。     * ctx.getBean(BeanID,类型);     */    Axe axe = ctx.getBean("axe2",Axe.class);    System.out.println(axe);    //getBeanNamesForType 获取某个类型的全部Bean ID    String[] names = ctx.getBeanNamesForType(Axe.class);    //输出全部的BeanID    System.out.println(Arrays.toString(names));}

组件扫描方式创建JavaBean

Spring 提供了更加“简洁”的创建JavaBean的注解:

  • @Component,标注在类上

  • @ComponentScan 组件扫描注解,标注在配置类上

  • Spring在初始化的时候,会根据@ComponentScan 扫描约定的包,创建其中标注了@Component的类型对象。

工作原理:

组件扫描方式和@Bean方式的区别:

  • 组件扫描方式:

    • 需要配置@ComponentScan (只需要配置一次)

    • 创建类,在类上标注@Component

    • 书写简单,适合自己编写 的类型,创建Bean对象时使用。

  • @Bean方式

    • 创建类

    • 在配置类上使用 @Bean创建对象

    • 适合第三方(别人)提供Java类,无法修改其代码的情况下,使用@Bean注解声明JavaBean对象。

案例:

  1. 配置类Config类中进行编写

@Configuration/** * 在配置类中标注@ComponentScan("cn.tedu.bean")以后 * Spring 在启动后会自动扫描 cn.tedu.bean 包里面的所有类 * 如果包中的类标注类 @Component 注解,就会自动的创建 这个类型的对象 * 并且存储到Spring中。使用时候可以getBean(类型)获得该对象。 */@ComponentScan("cn.tedu.bean")public class Config {    //...}

2.Java类创建一个bean包进行编写以下代码

package cn.heimao.bean;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/** * 如果类@Component,SPring启动时候扫描到DemoBean * 时候就会在Spring中创建 DemoBean类型的对象。 */@Componentpublic class DemoBean implements Serializable { String name = "Demo"; public DemoBean(){ } public DemoBean(String name){ this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; }}

3.测试

@Testpublic void demoBean(){    /**     * 获取组件扫描功(ComponentScan)能创建的对象     */    DemoBean demoBean = ctx.getBean(DemoBean.class);    System.out.println(demoBean);}

@Component注解时候,BeanID是什么?

  • 默认情况下:

    • 如:类名MYDemoBean 其默认的BeanID是 MYDemoBean

    • 如:类名DemoBean 其默认BeanID是 “demoBean”

    • 如果标准的驼峰命名法的类名,其BeanId是类首字母小写:

    • 如果类名有连续两个大写字母,则就是类名

  • 可以利用@Component注解参数修改BeanID(很少使用)

    • 如:@Component(“iDemoBean”)

案例:

/** * 如果类@Component,SPring启动时候扫描到DemoBean * 时候就会在Spring中创建 DemoBean类型的对象。 */@Componentpublic class DemoBean implements Serializable {    String name = "Demo";    public DemoBean(){    }    public DemoBean(String name){        this.name = name;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

创建一个ExampleBean类

import java.io.Serializable;
public class ExampleBean implements Serializable {}

在配置类中编写方法Config

@Bean    public ExampleBean exampleBean() {   return new ExampleBean();    }
/** * @Component 声明的Bean 如果连续两个大写字母,则BeanID就是类名 */@Componentpublic class MYDemoBean implements Serializable {    //...}
/** * 利用@Component("myDataBean")的参数将BeanID修改为 myDataBean */@Component("myDataBean")public class DataBean implements Serializable {
}

测试

@Testpublic void testBeanId(){    //检查 默认情况下 @Component组件的BeanID: demoBean    String[] names = ctx.getBeanNamesForType(DemoBean.class);    System.out.println(Arrays.toString(names));    //检查 类名连续两个大写字母时候,BeanID就是类名 ?    names = ctx.getBeanNamesForType(MYDemoBean.class);    System.out.println(Arrays.toString(names));    //可以使用 @Component 的参数修改默认的BeanID    names = ctx.getBeanNamesForType(DataBean.class);    System.out.println(Arrays.toString(names));}

Spring 提供了多个用于声明bean注解

  • @Component:用于声明通用组件

  • @Service        :用于声明业务层组件,在《稻草问答》项目中讲解

  • @Controller  :用于声明控制器组件,在《稻草问答》项目中讲解

  • @Repository:用于声明持久层组件,在《稻草问答》项目中讲解

上述注解功能基本一样,都可以用于声明Bean对象!!

测试:上述注解功能基本一样?

案例:

/** * 利用@Component("myDataBean")的参数将BeanID修改为 myDataBean * @Component == @Service 功能基本一样 *               @Controller *               @Repository * */@Service("myDataBean")public class DataBean implements Serializable {
}

案例 利用Spring 管理数据库连接池

Spring 不仅可以管理我们自己定义的类,创建JavaBean。也可以管理其他API的类,创建对象。

比如:使用Spring管理数据库连接池对象。

  • 使用DBUtil管理数据库连接池,需要编码,容易错误

  • 利用Spring管理数据库连接池,编码少,不容易错误(项目中广泛使用!!!)

使用Spring管理数据库连接池对象:

  • 利用Maven导入数据库连接池和数据库驱动程序

  • 数据库连接池的核心对象 DruidDataSource

    • @Bean创建DruidDataSource的对象

  1. 导入包:

<!-- 数据库连接池 --><dependency>    <groupId>com.alibaba</groupId>    <artifactId>druid</artifactId>    <version>1.1.21</version></dependency><!-- 连接MySQL数据库的依赖 --><dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId>    <version>8.0.15</version></dependency>
  1. 在Config类中声明Bean

/** * 在Config类中使用@Bean注解声明数据库连接池对象 * 利用Spring管理数据库连接池对象 druidDataSource * DruidDataSource 来自阿里巴巴的连接池API */@Beanpublic DruidDataSource druidDataSource(){    DruidDataSource dataSource = new DruidDataSource();    //创建数据库连接池对象,必须设置数据库连接参数,否则会异常    dataSource.setDriverClassName("com.mysql.jdbc.Driver");    dataSource.setUrl("jdbc:mysql://localhost:3306/mysql?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true");    dataSource.setUsername("root");    dataSource.setPassword("root");
return dataSource;}
  1. 测试:

/** * 测试数据库连接池 */@Testpublic void testDataSource() throws SQLException {    DruidDataSource dataSource = ctx.getBean(DruidDataSource.class);    System.out.println(dataSource);    //注意,到包 java.sql.Connection,不要搞错误了    //连接接到数据库,如果没有连接参数,就会出现错误!    Connection conn = dataSource.getConnection();    conn.close();    //如果不设置数据库连接参数,就会报错误}

作业

  1. 重新创建Spring项目,重新编写全部课堂案例

  2. @Bean练习

    1. 编写一个类 Saw(锯)

    2. 在配置类Config中利用@Bean创建Saw类型的Bean对象

    3. 在测试案例中getBean获得Saw类型的Bean对象

    4. 在测试案例中检查Saw类型的Bean对象的BeanID

  3. @Component 练习

    1. 编写一个类 Worker(工人)

    2. 使用@Component 声明JavaBean

    3. 在配置类中标注 @ComponentScan

    4. 测试案例中测试JavaBean 和 BeanID

  4. 重新编写@Bean管理数据库连接池的案例。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多