Spring全注解开发---常用注解笔记整理

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring全注解开发---常用注解笔记整理相关的知识,希望对你有一定的参考价值。

Spring全注解开发


@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全注解开发---常用注解笔记整理的主要内容,如果未能解决你的问题,请参考以下文章

Spring 最常用的 7 大类注解,史上最强整理!

spring学习笔记四:spring常用注解总结

Spring Boot常用注解和原理整理

Spring 最常用的 7 大类注解,史上最强整理!

Spring 最常用的 7 大类注解,史上最强整理!

Spring 最常用的 7 大类注解,史上最强整理!