Spring注解
一、使用xml方式将Bean注入到IOC
1.创建Bean类
2.创建xml配置文件
3.读取xml配置文件
二、@Bean和@Configuration
- 给容器中注册组件的方式:
-
包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)[适用于自已写的类]
-
@Bean[适用于导入的第三方包里面的组件]
-
@Import[快速给容器中导入一个组件,同样适用于导入的第三方包里面的组件]
-
使用Spring提供的FactoryBean(工厂Bean)
使用@Bean和@Configuration注解的方式将Bean注入到IOC
1.编写配置类
该配置类相当于beans.xml,在beans.xml中使用xml标签配置的内容,都可以在此配置类中配置,如注入Bean、包扫描等
2.读取配置类
3.指定bean的名字
三、@ComponentScan和@ComponentScans
使用@ComponentScan注解进行包扫描
1.以前需要在配置文件中使用<context:component-scan>
标签来配置包扫描,然后spring会自动扫描标注了@Controller、@Service、@Repository、@Component注解的类,将这些类注入到IOC中。
2.配置文件中添加包扫描注解
3.标识@Controller、@Service、@Repository、@Component注解
3.测试
4.@ComponentScan扫描时排除某些包或组件
5.@ComponentScans配置多个扫描规则
@ComponentScans中可以配置多个@ComponentScan
四、@Scope
1.默认的Bean是单实例的
2.配置成多实例
3.配置成单实例或多实例时,何时创建bean?
- 单实例
- 多实例
五、@Lazy
懒加载只用于单实例的bean
- 不开启懒加载
- 开启懒加载
六、@Conditional
按照一定的条件进行判断,满足条件才给容器中注册bean,@Conditional注解是springboot底层大量使用的注解
6.1 用在配置类中的方法上
需求:
如果系统是windows,给容器中注册(“bill”)
如果是linux系统,给容器中注册(“linus”)
1.创建条件类
创建的条件类叫实现Condition接口
- linux
- windows
2.配置类中使用@Conditional
3.测试
- windows系统
- linux系统
修改os.name的名字
需求:
如果ioc中存在名字叫person的bean,则进行…
1.定义配置类
6.2 用在配置类上
1.用在配置类上
2.测试
因为将os.name调成了linux,所以ioc中不会加载MainConfig2中配置的任何bean。
七、@Import
使用@Import注解来向容器中注册组件
7.1 @Import用法1
@Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
1.创建要注册的组件
2.配置类上使用@Import注解
7.2 @Import用法2
1.定义要导入的类:Blue类和Yellow类
2.定义一个类来实现ImportSelector接口,然后重写selectImports方法,selectImports方法返回的是要入到容器中组件名称
3.配置类上的@Import注解中配置MyImportSelector.class
4.测试
7.3 @Import用法3
1.定义一个要导入的类:RainBow类
2.定义一个类来实现ImportBeanDefinitionRegistrar接口,然后重写registerBeanDefinitions方法,在该方法中手动注册bean到容器中
3.配置类上的@Import注解中配置MyImportBeanDefinitionRegistrar.class
4.测试
八、FactoryBean
使用Spring提供的FactoryBean来将组件注册到容器。
- 创建一个Spring定义的FactoryBean的实现类,然后实现getObject方法、getObjectType方法、isSingleton方法
Spring会自动调用getObject方法,然后将该方法返回的对象注册到容器中
- 在配置类中将ColorFactoryBean注册到容器中
- 测试
- 获取Color组件
Color对象注册到容器中的名字是配置类中的方法名colorFactoryBean
虽然名字是colorFactoryBean,但是默认获取到的是FactoryBean的实现类调用getObject方法返回的对象,即Color
- 如何获取容器中的FactoryBean对象?
在容器中获取FactoryBean的实现类本身的对象,需要在id的前面加一个&符号
九、Bean的生命周期
bean会先创建对象,然后将对象注册到ioc中
单实例的bean会在Ioc容器关闭的时候销毁,但是多实例的bean不会在ioc容器关闭时销毁,需要手动销毁。
- 可以在beans.xml中使用init-method和destroy-method方法来指定bean初始化方法和销毁方法
- 使用@Bean注解的方式来初始化和销毁Bean
- 定义一个要注册到容器中的类
- 定义一个配置类来注册Bean
- 测试
- 意义
可以在bean创建的时候进行一些参数的设置,bean销毁的时候进行一些数据源,io流的关闭
- 通过让bean实现InitializingBean接口来实现bean的初始化逻辑,实现DisposableBean接口来实现bean的销毁逻辑
- 定义要注册到容器中的类
- 配置类中@Bean注解注册Cat
- 测试
- 使用JSR250提供的@PostConstruct注解和@PreDestroy注解
- 创建一个类并标注@PostConstruct注解和@PreDestroy注解
-
配置类中使用@Bean注解注册Dog
-
测试
- 使用bean后置处理器
bean的后置处理器可以在bean的初始化前和初始化后进行一些操作。
- 定义bean的后置初始器,并实现 BeanPostProcessor接口
- 使用@Bean注解或@Component注解将后置处理器加入到容器中
- 测试
十、@Value和@PropertySource
@Value注解可以给对象中的属性赋值
- 创建配置文件
- 指定配置文件路径
- 可以使用beans.xml来指定配置文件路径
- 可以在配置类中使用@PropertySource注解来指定配置文件的路径
- 使用@Value注解赋值
-
配置类中注册Person
-
测试
- 因为spring会把外部配置文件中的值加载到ConfigurableEnviromment中,所以可以直接从ConfigurableEnviromment中读取配置文件中的值
十一、@Autowired和@Qualifier
详见spring-common-annotations.md
十二、自定义组件使用Spring底层的组件
自定义组件想要使用Spring底层的一些组件(ApplicationContext, BeanFactory, xxx)
自定义组件实现xxxAware,在创建对象的时候,会调用接口规定的方法注入相关的Spring底层组件,xxxAware全都实现自Aware接口。
xxxAware的功能,使用对应xxxProcessor来处理,如 ApplicationContextAware==>ApplicationContextAwareProcessor。
案例
- 创建自定义组件,实现xxxAware接口
- 配置文件中注册此自定义组件
- 测试
创建此组件的对象时会调用setApplicationContext方法、setEmbeddedValueResolver方法、setBeanName方法
十三、@Profile
Profile: Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能;
@Profile:环境标识注解,指定组件在哪个环境的情况下才能被注册到容器中,如果不指定,那么任何环境下都能注册这个组件
加了@Profile注解的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境。
@Profile注解也可以写在类上,写在类上时,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效。
没有添加@Profile注解的bean在,任何环境下都是加载的。
案例:多个数据源之间进行切换
- 配置类中将Test、Dev、Prod三个数据源注册到IOC容器
- 为三个数据源分别添加@Profile注解
dataSourceTest()方法上添加@Profile(“test”)
dataSourceDev()方法上添加@Profile(“dev”)
dataSourceProd()方法上添加@Profile(“prod”)
- 指定环境
- 使用命令行动态参数:在虛拟机参数位置加载 -Dspring.profiles.active=test
激活了加了@Profile(“test”)注解的数据源
- 代码的方式
激活了加了@Profile(“test”)注解和@Profile(“dev”)注解的数据源
十四、IOC小结
十五、AOP
aop指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式
通知方法:
- 前置通知(@Before):在目标方法(div)运行之前运行
- 后置通知(@After):在目标方法(div)运行结束之后运行(无论方法正常结束还是异常结束,都会通知)
- 返回通知(@AfterReturning):在目标方法(diy)正常返回之后运行
- 异常通知(@AfterThrowing):在目标方法(div)出现异常以后运行
- 环绕通知(@Around):动态代理,手动推进目标方法运行 (joinPoint.procced())
需要导入aop依赖
aop步骤:
案例:在业务逻辑运行的时候将日志迸行打印(方法之前、方法运行结束)
- 定义一个类
- 定义一个切面类
- 给切面类的目标方法标注何时何地运行(通知注解)
- 将切面类和业务逻辑类(目标方法所在类)都加入到容器中
- 必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
- 开启基于注解的aop模式
- beans.xml中开启
- 或配置类中开启
- 测试
- 可以在切面类中获取方法名、参数、返回值、异常
- 获取方法名和参数
JoinPoint joinPoint中包含方法名,参数列表等信息
- 获取返回值
Object result是方法返回的结果
- 获取异常信息
注意: Spring5的后置通知和最终通知和Spring4的不一样了
十六、@Transactional
给方法标注@Transactional注解,表示当前方法是一个事务方法
步骤:
- 开启事务管理
- 将事务管理器注册到容器中
- 添加@Transactional注解
案例:
- 创建数据源
- 创建Dao
- 创建Service,并添加@Transactional注解
- 开启事务管理功能
- 在配置文件中配置
- 或在配置类中配置
- 将事务管理器注册到容器中