Spring全注解开发---常用注解笔记整理
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring全注解开发---常用注解笔记整理相关的知识,希望对你有一定的参考价值。
Spring全注解开发
- @Configuration和 @Bean注解
- @ComponentScan
- @Scope
- @Lazy ---懒加载
- @Conditional ({condition})
- @Import
- 使用Spring提供的FactoryBean(工厂Bean)来注册容器
- Bean的生命周期(注解版本),通过@Bean注解指定Bean的初始化和销毁方法
- 属性赋值
- 自动装配
- @Profile
- 总结: 以上所有注解生效的前提是,对应所在的组件被加入到容器中
@Configuration和 @Bean注解
//配置类等于一起的spring.xml配置文件
@Configuration //标注当前是一个配置类
public class MyConfig
{
//给容器中注册一个Bean,类型为返回值类型
//id默认是用方法名作为id
@Bean(value = "dhy")//指定id
public people getPeople()
{
return new people("大忽悠",18);
}
}
测试:
public class Main
{
//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置
private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);
@Test
public void test()
{
people peo = ioc.getBean(people.class);
System.out.println(peo);
//获取对应组件在容器中的名字
String[] beans = ioc.getBeanNamesForType(people.class);
for (String bean : beans) {
System.out.println(bean);
}
}
}
@Configuration和 @Bean注解以及补充注解的详细说明,强推!!!
配合@Bean注解一起使用的@Scope注解,感兴趣可以看看
@ComponentScan
以前:
<!--包扫描,只要标注了@Controller,@Service,@Repository,@Component注解都会被扫描进来-->
<context:component-scan base-package="com.controller"></context:component-scan>
配置类:
@Configuration //标注当前是一个配置类
@ComponentScan("com.controller")
public class MyConfig
{ }
controller:
//@Controller("大忽悠")这里同样可以起一个别名
@Controller("大忽悠")//这里同样可以起一个别名
public class peoController
{}
测试:
public class Main
{
//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置
private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);
@Test
public void test()
{
//获取容器中所有定义的Bean的名字
String[] beans = ioc.getBeanDefinitionNames();
for (String bean : beans) {
System.out.println(bean);
}
}
}
扫描时指定排除和包含哪些注解,一定要禁用掉默认的扫描规则
@Configuration //标注当前是一个配置类
@ComponentScan(value = "com.controller",includeFilters = {
//按照注解排除,排除掉Controller注解
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)
}, //这里禁用掉默认的扫描规则
useDefaultFilters = false)
public class MyConfig
{ }
@Configuration //标注当前是一个配置类
@ComponentScan(value = "com.controller",excludeFilters = {
//按照注解排除,排除掉Controller注解
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)
}, //这里禁用掉默认的扫描规则
useDefaultFilters = false)
public class MyConfig
{ }
可以按照类型排除或者包含要扫描的组件:
@Configuration //标注当前是一个配置类
@ComponentScan(value = "com.controller",includeFilters= {
//按照注解包含,排除掉Controller注解
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class),
//按照类型包含要扫描的组件
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = peoController.class)
}, //这里禁用掉默认的扫描规则
useDefaultFilters = false)
public class MyConfig
{ }
自定义规则,指定要包含或者要排除的组件:
继承TypeFilter接口,重写扫描匹配方法:
public class MyTypeFilter implements TypeFilter
{
//MetadataReader:读取到当前正在扫描的类的相关信息
//MetadataReaderFactory: 可以获取到其他任何类的信息
public boolean match(MetadataReader metadataReader,
MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类注解信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的类信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
//获取当前类资源(类路径)
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
//如果当前类名包含peo,则不扫描
if(className.contains("peo"))
return false;
//否则扫描
return true;
}
}
配置类:
@Configuration //标注当前是一个配置类
@ComponentScan(value = "com.controller",includeFilters= {
//按照自定义规则
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
}, //这里禁用掉默认的扫描规则
useDefaultFilters = false)
public class MyConfig
{ }
peo没被扫描进来,完美
@Scope
@Configuration //标注当前是一个配置类
@ComponentScan(value = "com.controller")
public class MyConfig
{
@Scope("prototype")
@Bean(value = "dhy")//指定id
public people getPeople()
{
return new people("大忽悠",18);
}
}
prototype:多实例的
ioc容器启动并不会去调用方法创建对象放在容器中,而是每次获取的时候才会调用方法创建对象
singleton:单实例的(默认值)
ioc容器启动时会调用方法创建对象放到ioc容器中,以后每一次获取就是直接从容器(map.get())中拿
request:同一次请求创建一个实例
session:同一个session创建一个实例
@Lazy —懒加载
@Configuration //标注当前是一个配置类
@ComponentScan(value = "com.controller")
public class MyConfig
{
@Lazy
@Bean(value = "dhy")//指定id
public people getPeople()
{
return new people("大忽悠",18);
}
}
懒加载:
单实例bean:默认在容器启动的时候创建对象
懒加载:容器启动不创建对象,第一次使用(获取)Bean创建对象,并初始化
@Conditional ({condition})
@Conditional: 按照一定的条件进行判断,满足条件给容器中注册Bean
LinuxCondition:
//判断是否linux系统
public class LinuxCondition implements Condition
{
/*
* ConditionContext:判断条件能使用的上下文环境
* AnnotatedTypeMetadata:注释信息
*
* */
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//1.能获取到ioc容器使用的BeanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//2.获取类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//3.获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//4.获取到bean定义的注册类:可以判断容器中的Bean的注册情况,也可以给容器中注册Bean
BeanDefinitionRegistry registry = conditionContext.getRegistry();
//获取当前操作系统名字
String property = environment.getProperty("os.name");
if(property.contains("linux"))
return true;
return false;
}
}
windowsCondition:
//判断是否windows系统
public class WindowsCondition implements Condition
{
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//3.获取当前环境信息
Environment environment = conditionContext.getEnvironment();
//获取当前操作系统名字
String property = environment.getProperty("os.name");
if(property.contains("Windows"))
return true;
return false;
}
}
配置类:
//标注在类上,则只有符合条件时,当前配置类及其里面注册的Bean才会生效
//@Conditional({WindowsCondition.class})
@Configuration //标注当前是一个配置类
public class MyConfig
{
@Conditional({WindowsCondition.class})
@Bean
public people getWindows()
{
return new people("windows系统",18);
}
@Conditional(LinuxCondition.class)
@Bean
public people getLinux()
{
return new people("Linux系统",18);
}
}
给容器中注册组件方式:
1:包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)
2:@Configuration注解标注类的会被放到容器中,因为AnnotationConfigApplicationContext(MyConfig.class),以前是通过配置文件的方式启动容器,现在是通过加载配置类的方式启动容器,并且@Configuration是个复合注解–里面由@Component等注解组成
3.@Bean导入第三方包里面的组件
4.@Import:快速的给容器中导入一个组件
@Import
@Import导入组件,id默认是全类名
配置类:
@Configuration //标注当前是一个配置类
//这里没有进行包扫描,所以在不进行导入的情况下peoController是不会被注册到容器中的
@Import({peoController.class,people.class})
public class MyConfig
{
@Conditional({WindowsCondition.class})
@Bean
public people getWindows()
{
return new people("windows系统",18);
}
@Conditional(LinuxCondition.class)
@Bean
public people getLinux()
{
return new people("Linux系统",18);
}
}
peoController:
@Controller("大忽悠")//这里同样可以起一个别名
public class peoController
{}
测试:
public class Main
{
//传入的是配置类的位置,一开始是加载配置类,之前是加载配置文件的位置
private ApplicationContext ioc= new AnnotationConfigApplicationContext(MyConfig.class);
@Test
public void test()
{
//获取容器中所有定义的Bean的名字
String[] beans = ioc.getBeanDefinitionNames();
for (String bean : beans) {
System.out.println(bean);
}
}
}
这里@Controller(“大忽悠”)已经起了一个别名,只是没被扫描到容器中,所以这里使用其别名作为id
自定义选择器导入组件
MyImportSelector:
//自定义逻辑返回需要导入的组件
public class MyImportSelector implements ImportSelector
{
//返回值就是要导入到容器中的组件的全类名
//AnnotationMetadata:当前标注@Import注解的类的所有信息
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//方法不要返回null
return new String[]{"com.Pojo.rea", "com.Pojo.ha"};
}
}
MyConfig:
@Configuration //标注当前是一个配置类
//加入自定义导入选择器
@Import({peoController.class,people.class,MyImportSelector.class})
public class MyConfig
{
@Conditional({WindowsCondition.class})
@Bean
public people getWindows()
{
return new people("windows系统",18);
}
@Conditional(LinuxCondition.class)
@Bean
public people getLinux()
{
return new people("Linux系统",18);
}
}
ImportBeanDefinitionRegistrar 手动注册Bean到容器
MyImportBeanDefinitionRegister:
public class MyImportBeanDefinitionRegister implements ImportBeanDefinitionRegistrar
{
/*
* AnnotationMetadata:当前类的注解信息
* BeanDefinitionRegistry:BeanDefinition注册类
* 把所有需要添加到容器中的Bean,调用
* BeanDefinitionRegistry.registerBeanDefinition手工注册起来
* */
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
boolean ha = beanDefinitionRegistry.containsBeanDefinition("com.Pojo.rea");
boolean rea = beanDefinitionRegistry.containsBeanDefinition("com.Pojo.ha");
if(ha&&rea)
{
//指定Bean定义信息(Bean的类型,Bean的作用域...)
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(dhy.class);
//指定Bean名
beanDefinitionRegistry.registerBeanDefinition("手动组成的Bean",rootBeanDefinition);
}
}
}
MyConfig:
@Configuration //标注当前是一个配置类
//加入自定义导入选择器
@Import({people.class,MyImportSelector.class,MyImportBeanDefinitionRegister.class})
public class MyConfig
{
@Conditional({WindowsCondition.class})
@Bean
public people getWindows()
{
return new people("windows系统",18);
}
@Conditional(LinuxCondition.class)
@Bean
public people getLinux()
{
return new people("Linux系统",18);
}
}
使用Spring提供的FactoryBean(工厂Bean)来注册容器
自定义工厂类继承FactoryBean
//创建一个Spring定义的工厂Bean
public class MyFactoryBean implements FactoryBean<Mine> {
//返回一个Mine对象,这个对象会添加到容器中
public Mine getObject() throws Exception {
return new Mine();
}
public Class<?> getObjectType() {
return Mine.class以上是关于Spring全注解开发---常用注解笔记整理的主要内容,如果未能解决你的问题,请参考以下文章