Spring第二天:Spring基于注解的IOC已经IOC案例
- 细说一天的学习内容:
- Spring中IOC的常用注解
- 案例使用XML方式和注解方式实现单表的CRUD操作
- 持久层技术选择:dbutils
- 改造基于注解的IOC案例,使用纯注解的方式实现
- Spring的一些新注解使用
- Spring和Junit整合
1. Spring基于注解的IOC配置
- 曾经XML的配置:
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl" scope="" init-method="" destroy-method=""> <property name="" value="" | ref=""></property> </bean>
- 对应的注解:
- 用于创建对象的:
- 他们的作用就和在XML配置文件中编写一个标签实现的功能是一样的
@Component: 作用:用于把当前类对象存入Spring容器中 属性: value:用于指定bean的id。(当我们不写时,它的默认值是当前的类名,且首字母改小写) 由Component衍生的注解: Controller:一般用在表现层 Service:一般用在业务层 Repository:一般用在持久层 * 以上三个注解他们的作用和属性与Component是一模一样。 * 他们三个是Spring框架为我们提供明确的三层使用的注解, 使我们的三层对象更加清晰
- 用于注入数据的:
- 他们的作用就和在XML配置文件中的bean标签中写一个标签的作用是一样的
@Autowired: 作用:自动按照类型注入。 * 只要容器中有唯一的一个bean对象类型和要注入的变量类型 匹配,就可以注入成功。 * 如果ioc容器中没有任何bean的类型和要注入的变量类型匹 配,则报错。 * 如果ioc容器中有多个类型匹配时:首先按照类型圈定出来匹 配出来的对象,然后使用变量名称作为bean的id,在圈定的里 面在找那个一样。 * 问题:所以匹配多个的时候找不到一样的就没法注入,所 以要==用到@Qualifier注解== 出现位置: 可以是变量上,也可以是方法上 细节: 在使用注解注入时,set方法就不是必须的了 * 举例: @Autowired private IAccountDao accountDao = null; ============================== @Qualifier注解 作用:在按照类中注入的基础之上再按照名称注入。它在给类成员注入 时不能单独使用(需要在上面写@Autowired)。但是在给方法参数注入时可以(稍后我们讲) 属性: value:用于指定注入bean的id。 =============================== @Resource注解 作用:直接按照bean的id注入。它可以单独使用。 属性: name:用于指定注入bean的id。 =***=以上三个注入都只能注入其他bean类型的数据,而基本类型和String类 型无法使用上述注解实现。== =***=另外,集合类型的注入只能通过XML来实现== ================================ @Value注解 作用:用于注入基本类型和String类型的数据 属性: value:用于指定数据的值。它可以使用Spring中SpEL(也就是Spring的el表达式) SpEL的写法:${表达式}
- 怎么注入成功及Spring的IOC是一个什么结构?(此时只有一个类型匹配)
- 如果ioc容器中有多个类型匹配时:
- 用于改变作用范围的:
- 他们的作用就和在bean标签中使用scope属性实现的功能是一样的
@Scope注解 作用:用于指定bean的作用范围 属性: value:指定范围的取值。常用取值:singleton(单例)和prototype(多例) 默认情况为单例
- 和生命周期相关:(了解)
- 他们的作用就和在bean标签中使用init-method和destroy-method的作用是一样的
@PreDestroy注解 作用:用于指定销毁方法 注:多例不负责 @PostConstruct 作用:用于指定初始化方法
- 用于创建对象的:
- 使用注解的前提步骤:
- 告知Spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,而是一个名称为context名称空间和约束中
- 在Spring中index.html文档中点core,然后搜索
xmlns:
将这段话复制到bean.xml中 - 然后使用context:component-scan来:扫描指定的范围内所有的注解
- 在Spring中index.html文档中点core,然后搜索
- 告知Spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,而是一个名称为context名称空间和约束中
- 图例实现用于创建对象的:
1.
- 注:当注解中只能给一个属性赋值,并且属性名是value时,value可以省略
- @component(“accountService”):指定的id
3.
- 注:当注解中只能给一个属性赋值,并且属性名是value时,value可以省略
2. 用上面方式做完出现的两个问题
- 问题一,测试类中有很多冗余代码(junit问题)
- 解决问题一
- 开发工程师的解决方法:
- Spring整合Junit分析:
- 应用程序的入口
- main方法
- junit单元测试中,没有main方法也能执行
- junit集成了一个main方法
- 该方法就会判断当前测试类中哪些方法有 @Test注解
- junit就让有Test注解的方法执行
- junit不会管我们是否采用spring框架
- 在执行测试方法时,junit根本不知道我们是不是使用了spring框架
- 所以也就不会为我们读取配置文件/配置类创建spring核心容器
- 由以上三点可知
- 当测试方法执行时,没有Ioc容器,就算写了Autowired注解,也无法实现注入
- 应用程序的入口
- Spring整合Junit配置(解决)
- 导入Spring整合Junit的jar包(坐标)
- spring-test
- 使用Junit提供的一个注解把原有的main方法替换了,替换成spring提供的。
@Runwith
- 告知Spring的运行器,Spring和ioc创建是基于XML还是注解的,并且说明位置。
@ContextConfiguration *locations:指定xml文件的位置,加上classpath关键字,表示在类路径下 * classes:指定注解类所在地位置
- 注解的方式:
- xml的方式:
- 第二步:表示自动按照类型注入
- 注解的方式:
- 注:当我们使用Spring 5.x版本的时候,要求junit的jar包必须是4.12及以上
- 导入Spring整合Junit的jar包(坐标)
- 开发工程师的解决方法:
- 问题二,注解IOC中还是用XML的问题,,上面注解只能去掉自己写的类,比如引用的jar中的还是需要配置。
- 解决问题二
- 写一个配置类(它的作用和bean.xml一样)
- Spring中的新注解
@Configuration 作用:指定当前类是一个配置类 细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。 ============== @ComponentScan 作用:用于通过注解指定Spring在创建容器时要扫描的包 属性: value:它和basePackages的作用是一样的,都是用于指定创建容 器时要扫描的包。 注: 我们使用了这个注解就等同于在XML中配置了: <context:component-scan base-package="com.itheima"></context:component-scan>
- 引用的jar中的在配置类中的替换
- 存在的问题,没有存入到Spring容器中
- 解决:用一个新注解
@Bean 作用:用于把当前方法的放回值作为bean对象存入Spring的ioc容器中。 属性: name:用于指定bean的id。当不写时,默认值是当前方法的名称 细节: 当我们使用注解配置方法时,如果方法有参数,Spring框架会去容器中查找有没有可用的bean对象。 查找的方式和Autowired注解的作用是一样的。
- 存在的问题,没有存入到Spring容器中
- 代码演示
- 解决结果:bean.xml就可以删除了
- 但是需要将测试类中获取容器改为:
- 原来的写法:
- 但是需要将测试类中获取容器改为:
- 写一个配置类(它的作用和bean.xml一样)
- 还存在的一些细节:
- QueryRunner从单例改为多例:
- @Configuration注解中的一个细节:当配置类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
- 当我们配置多个配置类的时候:如果不写@Configuration注解时候可以在上面对象的参数中写入对应配置类的名字。
- 如果两个都不想写。
- 用到下面的注解:
@Import 作用:用于导入其他的配置类 属性: value:用于指定其他配置类的字节码。 当我们使用Import注解之后,有Import注解的类就是父配置类,导入的都是子配置类。
- 使用案例:
- 创建数据源对象出现的冗余
- 解决:
- 先创建好配置文件
- 替换后
- 上一步需要读取配置文件所以要用到下面的注解
@PropertySource 作用:用于指定properties文件的位置 属性: value:指定文件的名称和路径。 关键字:classpath,表示类路径下
- 代码案例:
- 代码案例:
- 改造后:
- 先创建好配置文件
- Qualifier注解的另一种用法
- 当有多个数据库且名字不同时:(无法用类型匹配,或者多个匹配,并且形参无法在多个匹配中找到符合的id时)
- 当有多个数据库且名字不同时:(无法用类型匹配,或者多个匹配,并且形参无法在多个匹配中找到符合的id时)
- QueryRunner从单例改为多例:
3. 实际开发中注解和XML应该如何选择
- 就职单位
- 纯XML:配置有复杂性
- 纯注解:没有带来便捷,,跟复杂
- 存在别人写好的jar包中:用XML
- 存在自己的中:用注解