Spring5常用注解使用介绍

前言

      金九银十之际,又到了面试的黄金时段,相信每位猿友或多或少再被影响着…

      翻出许久的面试总结册,陷入沉思中…(这玩意多多少少就是有些废头发)…

      圆规正转,今日份总结 spring5中常用注解的使用方法及一些心得。

      在此,记录一下,分享给大家。


注解介绍

      spring5中常用注解,大致可以归为四类组件:

          配置类组件、赋值(自动装配)组件、织入组件、切面组件。


配置组件(Configure Components)

  • @Configuration: 用于定义配置类,可替换XML配置文件,被注解的类内部包含一个或多个@Bean注解方法。可以被AnnotationConfigApplicationContext或者AnnotationConfigWebApplicationContext 进行扫描。用于构建bean定义以及初始化Spring容器。

    /**
     * 配置类
     */
    @Configuration
    public class YysConfig {
          
          
    
        @Bean
        public Apple apple() {
          
          
            return new Apple();
        }
    
        @Bean("banana_bean")
        public Banana banana() {
          
          
            return new Banana();
        }
    
        @Bean
        public Pear pear() {
          
          
            return new Pear();
        }
    }
    
    /**
     * 测试类
     */
    public class YysTest {
          
          
    
        @Test
        public void test() {
          
          
            ApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class);
            System.out.println("\n----------输出结果----------\n");
            System.out.println(app.getBean("apple")); // 默认使用方法名
            System.out.println(app.getBean("banana_bean")); // 配置别名优先使用别名,用发方法名报错
            System.out.println(app.getBean("pear"));
        }
    }
    

    @Configuration

  • @ComponentScan: 扫包,相当于xml配置文件中的context:component-scan,默认会扫描该类所在包下所有的配置类。

    支持自定义规则:

    /**
     * 配置类
     */
    @Configuration
    @ComponentScan(
            value = "com.yys.study.spring.annotation.config",
    //        includeFilters = {@Filter(type = FilterType.ANNOTATION, value = {Component.class} )}, // 使用某个注解
    //        includeFilters = {@Filter(type = FilterType.ASSIGNABLE_TYPE, value = {Pitaya.class} )}, // 使用具体某个类
            includeFilters = {
          
          @Filter(type = FilterType.CUSTOM, value = {
          
          YysTypeFilter.class} )}, // 自定义规则类
            useDefaultFilters = false
    )
    public class YysConfig {
          
          
    }
    
    /**
     * 自定义规则类
     */
    public class YysTypeFilter 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 + "------------");
            // 筛选出包含"Test"的类
            if (className.contains("Test")) return true;
    
            return false;
        }
    
    }
    
    /**
     * 测试类
     */
    public class YysTest {
          
          
    
        @Test
        public void test() {
          
          
            ApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class);
            String[] beanDefinitionNames = app.getBeanDefinitionNames();
    
            System.out.println(Arrays.toString(beanDefinitionNames)
                    .replaceAll("\\[|\\]", "")
                    .replaceAll(", ", "\n"));
        }
    }
    
  1. 不加自定义规则:
    不加自定义规则

  2. 加自定义规则:
    加自定义规则

  • @Scope: 用于指定scope作用域的(用在类上),默认单例

    /**
     * 配置类
     */
    @Configuration
    public class YysConfig {
          
          
    
        /**
         * 	0. 默認是單例
         * 	1. prototype - 原型,多例
         * 	2. singleton - 单例
         * 	3. request - 主要应用于web模块,同一次请求只创建一个实例
         * 	4. session - 主要应用于web模块,同一个session只创建一个对象
         */
        @Scope("prototype")
        @Bean
        public Apple apple() {
          
          
            return new Apple();
        }
    }
    

  • @Lazy: 延迟加载初始化

    /**
     * 配置类
     */
    @Configuration
    public class YysConfig {
          
          
    
        /**
         * 默认是非延时加载
         * 延时加载/懒加载只针对单例Bean起作用
         *
         * 作用:容器启动时不创建对象,调用对象时才创建
         */
        @Lazy
        @Bean
        public Apple apple() {
          
          
            return new Apple();
        }
    }
    

  • @Conditional: spring4开始提供,作用是按照一定的条件进行判断,满足条件给容器注册Bean

    /**
     * 配置类
     */
    @Configuration
    public class YysConfig {
          
          
    
        @Conditional(WindowsCondition.class)
        @Bean
        public Apple apple() {
          
          
            System.out.println("apple对象已添加至IOC容器");
            return new Apple();
        }
    
        @Conditional(LinuxCondition.class)
        @Bean
        public Banana banana() {
          
          
            System.out.println("banana对象已添加至IOC容器");
            return new Banana();
        }
    }
    
    /**
     * 自定义规则类 - Windows
     */
    public class WindowsCondition implements Condition {
          
          
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
          
          
    
            ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
            Environment environment = conditionContext.getEnvironment();
    
            String osName = environment.getProperty("os.name");
            System.out.println("当前操作系统环境为:" + osName);
            if(osName.contains("Windows")) return true;
    
            return false;
        }
    }
    
    /**
     * 自定义规则类 - Linux
     */
    public class LinuxCondition implements Condition {
          
          
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
          
          
    
            ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
            Environment environment = conditionContext.getEnvironment();
    
            String osName = environment.getProperty("os.name");
            System.out.println("当前操作系统环境为:" + osName);
            if(osName.contains("Linux")) return true;
    
            return false;
        }
    }
    
    /**
     * 测试类
     */
    public class YysTest {
          
          
    
        @Test
        public void test() {
          
          
            ApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class);
            // 如当前操作系统环境为Windows -》 apple对象添加至IOC容器
            // 如当前操作系统环境为Linux -》 banana对象添加至IOC容器
        }
    }
    

    @Conditional

    知识点:IDEA更换操作系统环境的配置
    1. Run -> Edit Configurations
    2. VM options +参数配置:-ea -Dos.name=Linux


  • @Import: 导入外部资源,直接加载至ioc容器(导入的是全类名)

    /**
     * 配置类
     */
    @Configuration
    @Import(Apple.class)
    // @Import(value = {Apple.class, Banana.class})
    public class YysConfig {
          
          
    
    }
    
    /**
     * 测试类
     */
    public class YysTest {
          
          
    
        @Test
        public void test() {
          
          
            ApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class);
            String[] beanDefinitionNames = app.getBeanDefinitionNames();
    
            System.out.println(Arrays.toString(beanDefinitionNames)
                    .replaceAll("\\[|\\]", "")
                    .replaceAll(", ", "\n"));
        }
    }
    

    @Import

    【知识点】给IOC容器注册bean的方式:

    • @Bean 直接加载单个类
    • @ComponentScan 默认扫描(@Controller、@Service、@Repostory、@Component)
    • @Import 快速给容器导入Bean的方式
      a.@Import 直接参数导入
      b.自定义规则类,需实现ImportSelector接口
      c.实现ImportBeanDefinitionRegistrar接口,获得BeanDefinitionRegistry可以手动往IOC容器塞
    • FactoryBean 把需要注册的对象封装为FactoryBean
      a.FactoryBean:负责将Bean注册到IOC的Bean
      b.BeanFactory:从IOC容器中获得Bean对象

  • 对Bean生命周期的监控:

  1. 配置@Bean的参数

    /**
     * 火龙果
     */
    public class Pitaya {
          
          
    
        public Pitaya() {
          
          
            System.out.println("Pitaya初始化完成...");
        }
    
        public void before() {
          
          
            System.out.println("----- before -----");
        }
    
        public void service() {
          
          
            System.out.println("----- service -----");
        }
    
        public void after() {
          
          
            System.out.println("----- after -----");
        }
    }
    
    /**
     * 配置类
     */
    @Configuration
    public class YysConfig {
          
          
    
        @Bean(initMethod = "before", destroyMethod = "after")
        public Pitaya pitaya() {
          
          
            return new Pitaya();
        }
    }
    
    /**
     * 测试类
     */
    public class YysTest {
          
          
    
        @Test
        public void test() {
          
          
            AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class);
            Pitaya pitaya = (Pitaya) app.getBean("pitaya");
            pitaya.service();
            app.close(); // 关闭容器
        }
    
    }
    

    配置Bean参数

  2. 分别实现InitializingBean、DisposableBean接口

    /**
     * 橘子
     */
    @Component
    public class Orange implements InitializingBean, DisposableBean {
          
          
    
        public Orange() {
          
          
            System.out.println("Orange初始化完成...");
        }
    
        public void service() {
          
          
            System.out.println("----- 业务 -----");
        }
    
        @Override
        public void destroy() throws Exception {
          
          
            System.out.println("----- 销毁 -----");
        }
    
        @Override
        public void afterPropertiesSet() throws Exception {
          
          
            System.out.println("----- 初始化 -----");
        }
    }
    
    /**
     * 配置类
     */
    @Configuration
    @ComponentScan("com.yys.study.spring.entity")
    public class YysConfig {
          
          
    }
    
    /**
     * 测试类
     */
    public class YysTest {
          
          
    
        @Test
        public void test() {
          
          
            AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class);
            Orange orange = (Orange) app.getBean("orange");
            orange.service();
            app.close(); // 关闭容器
        }
    }
    

    实现InitializingBean/DisposableBean接口

  3. 使用@PostConstruct和@PreDestory注解

    /**
     * 西瓜
     */
    @Component
    public class Watermelon {
          
          
    
        public Watermelon() {
          
          
            System.out.println("Watermelon初始化完成...");
        }
    
        @PostConstruct // 初始化之后调用
        public void before() {
          
          
            System.out.println("----- before -----");
        }
    
        public void service() {
          
          
            System.out.println("----- 业务 -----");
        }
    
        @PreDestroy // 对象销毁前调用
        public void after() {
          
          
            System.out.println("----- after -----");
        }
    }
    
    /**
     * 配置类
     */
    @Configuration
    @ComponentScan("com.yys.study.spring.entity")
    public class YysConfig {
          
          
    }
    
    /**
     * 测试类
     */
    public class YysTest {
          
          
    
        @Test
        public void test() {
          
          
            AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class);
            Watermelon watermelon = (Watermelon) app.getBean("watermelon");
            watermelon.service();
            app.close(); // 关闭容器
        }
    }
    

    使用@PostConstruct和@PreDestory注解

  4. 自定义类实现 BeanPostProcessor接口 - 推荐,自己定义规则

    /**
     * 自定义控制类
     */
    @Component
    public class YysBeanPostProcessor implements BeanPostProcessor {
          
          
    
        @Nullable
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
          
          
            System.out.println("=== postProcessBeforeInitialization, " + beanName + ", " + bean);
            return bean;
        }
    
        @Nullable
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
          
          
            System.out.println("=== postProcessAfterInitialization, " + beanName + ", " + bean);
            return bean;
        }
    }
    
    /**
     * 葡萄
     */
    @Component
    public class Grapes {
          
          
    
        public Grapes() {
          
          
            System.out.println("Grapes初始化完成...");
        }
    
        public void service() {
          
          
            System.out.println("----- 业务 -----");
        }
    }
    
    /**
     * 配置类
     */
    @Configuration
    @ComponentScan({
          
          "com.yys.study.spring.annotation.lifecycle.beanpostprocessor", "com.yys.study.spring.entity"})
    //@ComponentScans(
    //        @ComponentScan("com.yys.study.spring.entity"),
    //        @ComponentScan("com.yys.study.spring.xxx")
    //)
    public class YysConfig {
          
          
    }
    
    /**
     * 测试类
     */
    public class YysTest {
          
          
    
        @Test
        public void test() {
          
          
            AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(YysConfig.class);
            Grapes grapes = (Grapes) app.getBean("grapes");
            grapes.service();
            app.close(); // 关闭容器
        }
    }
    

    实现 BeanPostProcessor接口


赋值(自动装配)组件(Injection Components)

  • @Component: 泛指组件,当组件不好归类的时候,可以使用此注解进行标注

  • @Controller: 用于标注控制层组件

  • @Service: 用于标注业务层组件

  • @Repository: 用于标注数据访问层组件,即DAO组件

  • @Value: 普通数据类型赋值

    1. 基本数据类型 @Value(“xxx”)
    2. 支持Spring EL表达式 @Value(#{8-5})
    3. 配合@PropertySource注解,通过配置文件赋值 @Value(“bird.color”)

    知识点:通过环境变量拿配置
    ApplicationContext app = new AnnotationConfigApplicationContext(MyConfig.class);
    Environment environment = app.getEnvironment();
    environment.getProperty(“bird.color”);


  • @Autowired: 默认按类型装配,如想按名称装配,可以结合@Qualifier注解一起使用

  • @PropertySource: 读取配置文件赋值

  • @Qualifier: 如存在多个实例配合使用,优先级高于@Autowired,但要和@Autowired配合使用

  • @Primary: 自动装配出现多个Bean候选者,被注解为@Primary的Bean作为首选者,否则将抛出异常

  • @Resource: 默认按名称装配,当找不到名称匹配的bean才会按类型装配,可以单独使用,优先级高于@Qualifier/@Autowired

    简单理解:
    @Autowired:根据类型注入
    @Resource:默认根据名字注入,找不到按照类型搜索
    @Autowired @Qualifier(“beanName”) :两个结合起来可以根据名字和类型注入

织入组件(Weave Components)

  • @ApplicationContextAware: 可以通过这个上下文对象得到Spring容器中的Bean

    /**
     * 当一个类实现 ApplicationContextAware接口之后,这个类就可以方便获得ApplicationContext中的所有bean。
     * 换句话说,就是这个类可以直接获取spring配置文件中,所有有引用到的bean对象
     */
    @Component
    public class AppUtils implements ApplicationContextAware {
          
          
    
        public static ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
          
          
            this.applicationContext = applicationContext;
        }
    
        /**
         * 获取applicationContext实例
         */
        public static ApplicationContext getApplicationContext() {
          
          
            return AppUtils.applicationContext;
        }
    
        /**
         * 通过名称获取Bean
         */
        public static <T> T getBean(String beanName) throws Exception {
          
          
            checkNull();
            return (T) applicationContext.getBean(beanName);
        }
    
        /**
         * 通过类型获取Bean
         */
        public static <T> T getBean(Class<T> clazz) throws Exception {
          
          
            checkNull();
            return (T) applicationContext.getBean(clazz);
        }
    
        /**
         * 校验 applicationContext是否为空
         *
         * @throws Exception
         */
        public static void checkNull() throws Exception {
          
          
            if (applicationContext == null)
                throw new Exception("applicationContext为空");
        }
    
    }
    

  • @BeanDefinitionRegistryPostProcessor: BeanDefinitionRegistryPostProcessor实现了BeanFactoryPostProcessor接口,是spring框架BeanDefinitionRegistry的后处理器,用来注册额外的BeanDefinition

    @Component
    @Slf4j
    public class PersonBeanDefinitionRegistryPostProcessor
    		implements BeanDefinitionRegistryPostProcessor {
          
          
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
        throws BeansException {
          
          
            // 注册Bean定义,容器根据定义返回bean
            log.info("register fruitsBean - 1");
            //构造bean定义
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
    				.genericBeanDefinition(Fruits.class);
            //设置依赖
            beanDefinitionBuilder.addPropertyReference("apple", "apple");
            BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder
    				.getRawBeanDefinition();
            //注册bean定义
            registry.registerBeanDefinition("fruitsBean1", personManagerBeanDefinition);
    
    	}
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
        throws BeansException {
          
          
            // 注册Bean实例,使用supply接口
            log.info("register fruitsBean - 2");
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
                .genericBeanDefinition(Fruits.class, () -> {
          
          
    	         Apple apple = beanFactory.getBean(Apple.class);
                     Fruits fruits = new Fruits();
                     fruits.setApple(apple);
                     return fruits;
             });
             BeanDefinition personManagerBeanDefinition = beanDefinitionBuilder
                .getRawBeanDefinition();
            ((DefaultListableBeanFactory) beanFactory)
              .registerBeanDefinition("fruitsBean2", personManagerBeanDefinition);
        }
    }
    

切面组件(Aspect Components)

  • @EnableTransactionManagement: 添加对事务管理的支持,等同于xml配置方式的 <tx:annotation-driven />

  • @Transactionl: 配置声明式事务信息



      大家好,我是猿医生 ~
      在码农的大道上,唯有自己强才是真正的强者,求人不如求己,静下心来,开始行动吧…


猜你喜欢

转载自blog.csdn.net/qq_42175986/article/details/120054032