![](http://image109.360doc.com/DownloadImg/2022/05/0518/244406410_1_20220505062440242_wm.jpeg)
Spring Famework Spring 框架:由Spring组织提供的开源软件框架,利用这套框架可以大大简化软件的开发过程,Spring采用一定规范约定框架的使用,来简化开发。使用时候必须准守这些规范。 框架:软件的半成品。利用框架编写软件可以大大简化开发过程。 Spring 框架核心功能: IoC/DI:控制反转和依赖注入 AOP:面向“切面(儿)”编程
IoC 控制反转主动控制:由应用程序代码,主动控制对象的创建,使用和销毁。 控制反转:是指对象的创建和销毁的控制权交给当前和环境(Spring),程序通过环境(Spring)拿到对象,使用对象。
一个控制反转例子: 李老板:控制斧子对象的创建和管理 光头强:从李老板手里拿到斧子去使用
Spring案例: Spring 框架,负责创建和管理对象 应用程序,从框架中获取对象,使用对象
下面的案例中,我们使用Spring管理简单对象,貌似繁琐,在日后才能体现其强大功能。
Spring HelloWorld案例目的:验证Spring IoC 可以实现对象的管理。 利用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!"; } }
创建一个配置类,告诉Spring如何管理斧子对象创建一个config包在包下面创建一个Config类
/** * Spring 的配置类 * 用于约定Spring管理的对象 * @Configuration Spring提供的注解,标注了@Configuration注解的 * 类,作为Spring的配置类! */ @Configuration public class Config { /** * @Bean 是Spring提供的注解,标注在方法上,方法的返回值就是 * Spring管理的对象。Spring 的内部就有了一个Axe类型的对象。 */ @Bean public Axe axe(){ return new Axe(); } }
初始化Spring,从Spring中获取创建好的斧子对象 验证斧子对象,如果证明有斧子对象,就说明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); } }
JUnitJUnit是开一的Java单元测试工具。用于软件组件单元测试。 使用步骤: 利用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? @Test public void axeTest(){ //初始化Spring AnnotationConfigApplicationContext ctx= new AnnotationConfigApplicationContext(Config.class); //从Spring中获取被管理的对象 Axe axe = ctx.getBean(Axe.class); //测试 System.out.println(axe); }
Spring IoC 的工作原理![](http://image109.360doc.com/DownloadImg/2022/05/0518/244406410_2_20220505062440694_wm.png)
Java BeanBean: 豆子 Java 豆子:按照一定规范编写的Java对象,这些对象具有类似的编码风格,有些象咖啡豆,每个都不同,但是都非常相似。 Java Bean 规范:行业中编写Java类的通行规范,几乎所有企业采用! 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 BeanIDSpring 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获取对象,解决冲突。
案例获取BeanID: 声明多个类型相同的Bean在Config类中进行编写
@Bean// Bean ID axe public Axe axe(){ return new Axe(); }
// 在Spring中创建了两个类型是Axe的对象 @Bean// Bean ID axe2 public 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 ID String[] names = ctx.getBeanNamesForType(Axe.class); //输出全部的BeanID System.out.println(Arrays.toString(names));
4.案例利用BeanID获取指定的Bean编写测试用例 Axe axe = ctx.getBean("axe2",Axe.class); System.out.println(axe);
JUnit 的 @Before @AfterBefore: 在...之前 After:在...之后 JUnit提供了测试案例生命周期注解,用于优化测试案例: 优点:不要每个测试案例都重新初始化资源。
在测试案例中利用@Before @After 封装创建Spring和回收Spring的代码,后续的案例就无需再创建Spring对象了!大大简化了测试案例的编写。 案例 AnnotationConfigApplicationContext ctx; @Before public void init(){ System.out.println("在测试案例之前"); ctx = new AnnotationConfigApplicationContext(Config.class); }
@After //destroy 销毁 public void destroy(){ System.out.println("在测试案例之后"); //关闭一下Spring, 回收Spring的资源 ctx.close(); }
测试案例(不用再次初始化Spring): @Test public 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)); }
组件扫描方式创建JavaBeanSpring 提供了更加“简洁”的创建JavaBean的注解: 工作原理: ![](http://image109.360doc.com/DownloadImg/2022/05/0518/244406410_3_2022050506244169_wm.png)
组件扫描方式和@Bean方式的区别: 案例: 配置类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类型的对象。 */ @Component public 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.测试 @Test public void demoBean(){ /** * 获取组件扫描功(ComponentScan)能创建的对象 */ DemoBean demoBean = ctx.getBean(DemoBean.class); System.out.println(demoBean); }
@Component注解时候,BeanID是什么?案例: /** * 如果类@Component,SPring启动时候扫描到DemoBean * 时候就会在Spring中创建 DemoBean类型的对象。 */ @Component public 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就是类名 */ @Component public class MYDemoBean implements Serializable { //... }
/** * 利用@Component("myDataBean")的参数将BeanID修改为 myDataBean */ @Component("myDataBean") public class DataBean implements Serializable {
}
测试 @Test public 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管理数据库连接池对象。 使用Spring管理数据库连接池对象: 导入包:
<!-- 数据库连接池 --> <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>
在Config类中声明Bean
/** * 在Config类中使用@Bean注解声明数据库连接池对象 * 利用Spring管理数据库连接池对象 druidDataSource * DruidDataSource 来自阿里巴巴的连接池API */ @Bean public 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; }
测试:
/** * 测试数据库连接池 */ @Test public void testDataSource() throws SQLException { DruidDataSource dataSource = ctx.getBean(DruidDataSource.class); System.out.println(dataSource); //注意,到包 java.sql.Connection,不要搞错误了 //连接接到数据库,如果没有连接参数,就会出现错误! Connection conn = dataSource.getConnection(); conn.close(); //如果不设置数据库连接参数,就会报错误 }
作业重新创建Spring项目,重新编写全部课堂案例 @Bean练习 编写一个类 Saw(锯) 在配置类Config中利用@Bean创建Saw类型的Bean对象 在测试案例中getBean获得Saw类型的Bean对象 在测试案例中检查Saw类型的Bean对象的BeanID
@Component 练习 编写一个类 Worker(工人) 使用@Component 声明JavaBean 在配置类中标注 @ComponentScan 测试案例中测试JavaBean 和 BeanID
重新编写@Bean管理数据库连接池的案例。
|