目录
作用: 用于把当前方法的返回值作为bean对象存入Spring的ioc容器中
-
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 告知spring在创建容器时要扫描的包,配置所需要的标签不是在beans的约束中,而是一个名称为context名称空间和约束中 --> <context:component-scan base-package="cn.lq"></context:component-scan> </beans>
-
Component
-
用于创建对象的注解
-
衍生注解
-
Controller
- 用于表现层
-
Service
- 用于业务层
-
Repository
- 用于持久层
- 功能和Component一模一样, 只要添加的位置不一样, Component用于除上面三层之外的类
-
-
-
数据注入
-
Autowried
- 无法注入基本类型和String类型
-
作用
- 自动按照类型注入
- 只要容器中有唯一一个的bean对象类型和要注入的变量类型匹配, 就可以注入成功, 否则就报错
- 如果有多个bean对象可以匹配的上(是他的实现类 或者是他的子类就可以匹配上)
- 再次根据要注入的成员变量的变量名字去匹配, 如果ioc容器中某一个bean对象的变量名能与之匹配, 就可以成功注入, 如果没有就报错, 如果有多个可以匹配也报错.
-
Qualifier
- 无法注入基本类型和String类型
- 作用: 在给类成员注入时不能单独使用, 但是给成员方法的参数注入时可以单独使用
- 作用位置: 可以作用到方法的参数上
- 属性
- value: 用于指定注入bean的id
-
Resource(常用)
- 无法注入基本类型和String类型
- 直接按照bean的id注入, 可以单独使用
- 属性
- name: 用于指定注入bean的id
-
Value(常用)
- 用于注入基本类型和String类型
- 属性
- value: 用于指定数据的值
- 可以使用Spring的SpEL(也就是spring中的el表达式)
- value: 用于指定数据的值
-
-
改变作用范围
-
默认是产生单例对象
-
使用注解: Scope
- prototype
- singleton
-
-
和生命周期相关
-
PreDestroy
- 用于指定销毁方法
- 作用于方法上
-
PostConstruct
- 指定初始化方法
- 作用于方法上
-
-
配置类
-
Configuration ComponentScan
-
个人理解
- 我们要去掉xml配置文件, 因为xml配置文件不方便, 不方便之处体现在, 如果我们打算使用注解开发, 那理论上我们只需要在xml文件中配置一下要扫描的包就可以啦, 但事实上, 有些类我们是无法给他加注解的, 比如果获取数据源的类, 那是我们导入的jar包, 我们无法修改他的源代码, 自然也就没办法往里面添加注解, 所以我们只能又在xml文件里面配置一下这个数据源的bean对象, 最终我们还是使用了xml文件进行配置bean对象, 这就与我们一开始打算使用注解开发的初心相违背, 所以配置类就应运而生, 包括下面的几个注解, 都是为配置类服务的, 其最终目的就是完全取代xml文件, 使用配置类来配置bean对象.
-
Configuration
- 作用: 指定当前类是一个配置类, 起作用和bean.xml一样, 是用来代替bean.xml的
- 细节: 当配置类作为AnnotationConfigApplicationContext对象创建的参数时, 该注解是可以省略不写的.
-
ComponentScan
- 作用: 用来指定Spring在创建容器时要扫描的包
- 属性:
- value: 指定包名
- basePackages: 等同于上面的属性value
-
-
Bean
-
作用: 用于把当前方法的返回值作为bean对象存入Spring的ioc容器中
-
属性:
- name: 用于指定bean对象的id, 如果不写, 默认是方法名
-
细节
- 当我们使用注解配置方法时, 如果方法有参数, Spring框架会去容器中查找有没有可用的bean对象, 查找的方式和Autowired注解的作用是一样的
-
-
Import
-
作用
- 往主配置类中导入其他配置类
-
属性
- value: 指定其他配置文件的字节码
- 当我们使用Import注解之后, 有Import注解的类就是父配置类, 而导入进来的就是子配置类
- value: 指定其他配置文件的字节码
-
使用场景
- 有时候我们可能配置许许多多的bean对象, 比如一系列jdbc的bean对象, 或者许多事务相关的bean对象, 这么多的代码全部写在一个配置类里面就不太妥当, 于是Import注解就派上了用场
-
使用方法
- 创建一个JdbcConfig类, 把配置bean对象的代码写进去
- 在主配置类中, 就可以删除JdbcConfig相关的bean对象配置代码了, 然后使用Import注解指定JdbcConfig的字节码文件即可
-
-
PropertySource
-
作用: 用于指定properties文件的位置
-
属性
- value: 指定文件的名称和路径
- 关键字: classpath: 表示类路径下
- value: 指定文件的名称和路径
-
-
Qualifier
- 在给方法传递参数时, Spring会自动从IoC容器中符合的bean对象, 但是有可能会找到多个符合的bean对象(它的子类或它的实现类都是符合的), 这个时候就用到Qualifier了
- 作用在参数上, 指定你想传进去的bean对象的id
-
@Bean("account") @Scope("prototype") public Account account(@Qualifier("ds1") DataSource dataSource) { return new Account(); }
-
-
-
什么时候使用注解什么时候使用xml
-
具体使用哪一种配置方式要根据公司里的规定
-
个人选择
-
尽量不要使用纯注解开发或者纯xml配置文件开发
- 不要使用纯注解开发: 因为当我们导入外部jar包的时候, 我们是没办法修改源码的, 自然就无法往里面添加注解
- 不要使用纯xml配置文件开发: 配置文件配置起来比较复杂
-
应该两者结合使用
- 自己创建的对象, 推荐使用注解创建bean对象, 在xml配置文件中只要指定要扫描的包即可
- 别人的对象, 在xml配置文件中配置即可
-
-
-
Spring整合Junit
-
概念
- 这部分内容主要想是解决开发工程师和测试工程师在测试项目的时候出现的差异问题
- 因为测试工程师和开发工程师掌握的代码知识不太一样, 开发人员觉得, 在test类中加一个Before注解就可以解决重复代码的问题变量初始化问题, 而测试工程师可能根本就不知道Before注解是什么意思, 或者测试人员想的是, 我只要把变量声明出来就应该可以拿出来直接使用了, 我不想关心那些多余的操作(读取配置文件 初始化变量等等), 所以就需要Spring去整合Junit单元测试, 去把测试工程师不想关心的细节直接封装起来.
-
Junit单元测试原理
- 测试类中是有一个main方法的, 我们之所以看不到是因为java已经把它封装起来了, 在我们手动执行带有Test注解的方法时, 事实上是先执行测试类内部的main方法, 由main方法再来调用带有Test注解的方法执行
-
原理
- 我们想达到的效果是: 你把变量声明出来就可以直接用, 因为我们会创建IoC容器, 然后把你声明出来的变量注入进去数据, 你就可以直接拿去用
-
具体实现
- 导入Spring整合Junit的jar包
- 使用注解把原来的main方法替换掉(原来的main方法并不会帮我们创建IoC容器)
- RunWith
- 告知Spring的运行器, IoC创建是基于xml还是基于注解, 并说明位置
- ContextConfiguration
- locations: 指定xml文件的位置, 加上classpath, 表明在类路径下
- classes: 指定注解类所在位置
- ContextConfiguration
- 注意事项
- Spring整合Junit需要Junit版本为4.12+, 否则报错
-
package cn.lq.test; import cn.lq.domain.Account; import cn.lq.service.ServiceAccount; import config.SpringConfiguration; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; /* author: lq time: 2020-04-25 19:16 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class TestServiceAccountImpl { @Autowired private ServiceAccount serviceAccountImpl; @Autowired private Account account; @Autowired private Account account1; // @Before // public void init() { // applicationContext = new ClassPathXmlApplicationContext("bean.xml"); // serviceAccountImpl = (ServiceAccount) applicationContext.getBean("serviceAccountImpl"); // } @Test public void testFindAll() { List<Account> accounts = serviceAccountImpl.findAll(); for (Account account : accounts) { System.out.println(account); } } @Test public void testFindById() { Account account = serviceAccountImpl.findById(2); System.out.println("account = " + account); } @Test public void testAdd() { account.setMoney((float) 20000); account.setName("lq"); serviceAccountImpl.add(account); } @Test public void testDelById() { serviceAccountImpl.delById(6); } @Test public void test01() { System.out.println(account == account1); } }
-