Spring注解驱动开发一:常用注解介绍

spring进阶学习–给容器中注册组件的常用注解

1、注解:@Configuration & @Bean

@Configuration配置在类上,类被称为配置类,配置类和配置文件是一个性质的
@Bean配置在方法上,用于注册一个bean到spring容器中,bean的类型是返回值类型,id默认为方法名,可以通过value=""设置bean的id
配置类:

package com.markus.config;
import com.markus.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * Author:markusZhang
 * degree of proficiency:
 * Date:Create in 2020/5/31 18:50
 */
@Configuration //告诉spring这是一个配置类   配置类==配置文件
public class SpringConfig {
    // 使用注解Bean在spring容器中注册一个bean,类型是返回值类型,id默认是方法名
    @Bean(value = "person")
    public Person person01(){
        return new Person("markus",20);
    }
}

测试类:

package com.markus.test;
import com.markus.bean.Person;
import com.markus.config.SpringConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * Author:markusZhang
 * degree of proficiency:
 * Date:Create in 2020/5/31 18:52
 */
public class SpringTest {
    @Test
    public void test(){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
        Person person = applicationContext.getBean(Person.class);
        System.out.println(person);

        String[] beanNamesForType = applicationContext.getBeanNamesForType(Person.class);
        for(String beanName:beanNamesForType){
            System.out.println(beanName);
        }
    }
}

测试结果:
在这里插入图片描述

2、注解:@ComponentScan

它的作用是进行包扫描,点进去它的源码看看
在这里插入图片描述
当我们在配置类上加上这样一个注解时,表明我们在启动容器的时候,需要将com.markus包下的文件注册到容器当中去
在这里插入图片描述
测试结果
在这里插入图片描述
我们来测试下excludeFilters
在这里插入图片描述
测试结果:就不包括service和controller了
在这里插入图片描述
includeFilter是一样的道理,将哪些配置扫描到容器当中去,这里就不测试了,但是需要注意的是,我们还需要配置一个useDefaultFilters=false,它默认是true的,如果为true的话,容器一启动就会扫描value指定的所有的包,我们需要修改它为false,然后指定哪些包需要被扫描的规则

扫描规则:
type:

  • FilterType.ANNOTATION:按照注解
  • FilterType.ASSIGNABLE_TYPE:按照给定的类型,也就是Bean的类
  • FilterType.ASPECTJ:使用ASPECTJ表达式
  • FilterType.REGEX:使用正则表达式
  • FilterType.CUSTOM:自定义规则

着重来看下自定义规则:
使用方式
在这里插入图片描述
自定义类:

package com.markus.config;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import java.io.IOException;
/**
 * Author:markusZhang
 * degree of proficiency:
 * Date:Create in 2020/5/31 20:23
 */
public class MyTypeFilter implements TypeFilter {
    /**
     * @param metadataReader : 读取到的当前正在扫描的类的信息
     * @param metadataReaderFactory : 可以获得其他任何类信息的
     */
    @Override
    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();
        System.out.println("--->"+className);
        if(className.contains("er")){
            return true;
        }
        return false;
    }
}

在这里插入图片描述

3、注解:@Scope,调整作用域

spring容器,默认Bean都是单实例的,但是可以设置
在这里插入图片描述
默认单实例下,IoC容器启动会调用方法创建对象,放到IoC容器中,以后每次获取直接就是从容器中拿。
如果调成是多实例,IoC容器启动时,不会调用方法创建对象,当我们获取对象的时候,才会去调用方法去创建对象,多次获取就会多次调用

4、注解:@Lazy

懒加载:(延迟加载)

  • 单实例Bean在启动容器的时候创建对象;
  • 懒加载:容器启动的时候不会去创建对象,第一次使用(获取)Bean的时候去创建,并初始化;但是在以后调用的时候就不会再去创建了,因为是单实例bean

5、注解:@Conditional

@Conditional:按照一定的条件判断,满足条件给容器添加Bean
在这里插入图片描述
创建三个bean实例,后两个是用到@Conditional注解,我们需要实现两个Condition类
LinuxCondition :

package com.markus.condition;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
 * Author:markusZhang
 * degree of proficiency:
 * Date:Create in 2020/5/31 21:50
 */
public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String property = context.getEnvironment().getProperty("os.name");
        if(property.toLowerCase().contains("linux")){
            return true;
        }
        return false;
    }
}

WindowsCondition:

package com.markus.condition;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;

/**
 * Author:markusZhang
 * degree of proficiency:
 * Date:Create in 2020/5/31 21:44
 */
public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // TODO: 2020/5/31 判断操作系统的类型来决定是否将Bean加入到容器当中

        // 1、可以获得bean工厂,用于创建bean和装配bean的
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 2、可以获得类加载器
        ClassLoader classLoader = context.getClassLoader();
        // 3、获取BeanDefinitionRegistry,可以注册bean、删除bean等等
        BeanDefinitionRegistry registry = context.getRegistry();
        // 4、获取操作系统的环境
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.toLowerCase().contains("window")){
            return true;
        }
        return false;
    }
}

测试结果:
在这里插入图片描述
@Conditional不仅可以放到方法上,也可以放到类上进行统一设置

6、注解:@Import

@Import:快速给容器中导入一个组件,它可以配置在类上面
在这里插入图片描述
在这里插入图片描述
还可以导入多个组件
在这里插入图片描述
在这里插入图片描述
还可以实现类ImportSelector,来判断哪些需要注册到容器当中
在这里插入图片描述
自定义实现类:

package com.markus.condition;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
/**
 * Author:markusZhang
 * degree of proficiency:
 * Date:Create in 2020/5/31 22:21
 */
public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.markus.bean.Blue","com.markus.bean.Yellow"};
    }
}

在这里插入图片描述

7、spring提供的FactoryBean(工厂Bean)

实现FactoryBean接口

package com.markus.bean;
import org.springframework.beans.factory.FactoryBean;
/**
 * Author:markusZhang
 * degree of proficiency:
 * Date:Create in 2020/6/1 22:14
 */
public class ColorFactoryBean implements FactoryBean<Color> {
    @Override
    public Color getObject() throws Exception {
        return new Color();
    }

    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

将这个工厂Bean加入到容器中,
1、默认获取到的是工厂Bean调用getObject创建的对象
2、要获取工厂Bean本身,我们需要在ID前加 & 字符,会得到工厂Bean的对象

总结

给容器中注册组件:

  • 通过包扫描+组件标注注解(@Controller、@Service、@Repository、@Component)[自己写的类]
  • @Bean[导入的第三方包里面的组件]
  • @Import[快速给容器中导入一个组件]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值