自定注解演示案例——SpringBoot如何自动识别pom.xml中的依赖并自动生成bean的

目的是 在pom.xml中未加入某个依赖时(即某个坐标未加载时)我们通过自定义注解的方式让某个对象的实例Bean不被创建

注意:

  • 这个并非必须掌握,是老师在演示SpringBoot如何自动识别pom.xml中的依赖并自动生成bean的
  • 此自定义注解由原始的非动态自定义注解改进,动态的添加类来实现自定义注解

代码结构:

使用Spring Initializer项目,按顺序创建

domain.User

package com.lwz.springboot_autoconfigure_confidition01.domain;

public class User {
}

config.UserConfig

package com.lwz.springboot_autoconfigure_confidition01.config;

import com.lwz.springboot_autoconfigure_confidition01.condition.ConditionOnClass;
import com.lwz.springboot_autoconfigure_confidition01.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class UserConfig {
    
//    @Conditional(ClassCondition.class)    //根据源码分析,返回true user的Bean将会被创建  反之false user的Bean将不会被创建
//                                            /*
//                                            可以发现 @Conditional 这个注解的value是指 <? extends Condition> 所有继承Condition的类的类型
//                                            于是在 @Condition中 有一个 matches()方法,用来返回是true 还是 false 作用是上面那句话 //......
//                                            但是现在的意思就是我这个@Conditional()中可以传入 一个继承Condition的类,该类中可以重写matches()方法
//                                            用来diy你想满足如何的条件,然后返回一个boolean的值,从而控制 某个坐标存在 时是否要创建该坐标对应类的bean
//                                             */
//                                            /*
//                                            也就是说通过@Conditional里的类重写的方法来决定该注解处的对象是否可以被生成Bean实例
//                                             */
    
    //创建一个Bean
    @Bean
    @ConditionOnClass({"redis.clients.jedis.Jedis","com.alibaba.fastjson.JSON"})  //多坐标引入,有一个坐标不存在即返回
    																	   //false,不创建Bean
	//    @ConditionOnClass("com.alibaba.fastjson.JSON")   //单一的坐标引入
    public User user(){
        return new User();
    }
}

condition.ConditionOnClass

package com.lwz.springboot_autoconfigure_confidition01.condition;

import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ClassCondition.class)
public @interface ConditionOnClass {
    String[] value();
}

Condition.ClassCondition

package com.lwz.springboot_autoconfigure_confidition01.condition;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.MultiValueMap;

import java.util.Map;


public class ClassCondition implements Condition {

    /**
     *
     * @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象
     * @param metadata 注解元对象。可以获取注解定义的属性值
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {

        /*
        在Spring的IOC容器中有一个User的 Bean,现要求:
        1.导入Jedis坐标后,加载该Bean,没导入,则不加载。
         */

        //有Condition01 改进的 不再将forName属性里的值 (即全类名)写死
        // 2.需求:导入通过注解的属性值value指定坐标后创建Bean
        //思路:判断 全类名.class 的文件是否存在

        //获取注解的属性值 value
        Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
        System.out.println(map);
        String[] value = (String[]) map.get("value");

        boolean flag = true;

        try {
            for (String classname : value) {
                Class<?> cls = Class.forName(classname);
            }
        } catch (ClassNotFoundException e) {
            flag = false;
        }
        return flag;
    }
}

自我描述:

1.自己创建一个类User,即之后我们所要使用的对象

2.然后创建一个UserConfig的配置类,标注@Configuration,此类用来生成Bean

3.然后创建ClassCondition类用来继承父类Condition并重写其matches方法,旨在之后可以自定义方法返回true/false

4.创建ConditionOnClass自定义注解,必须要加上@Conditional里的元注解(访问快捷键 鼠标中键),元注解旨在和该ConditionOnClass上标注的@Conditional的元注解保持一致,否则运行时会报错,@Conditional中需要加入你的ClassCondition.class 为啥只能加这个 这时可以查看@Conditional的内容,规定value的泛型只能为继承Condition的子类(说人话就是,这个子类中的重写matches的方法就是为了能让你DIY自己的方法以来满足生成所需要的true或false,然后控制Config类中标识该注解的Bean的生成)

5.在ConditionOnClass类中也可发现定义的value是一个String数组,在Configure中使用时,括号中可以填入多个全类名{“…”,“…”},然后需要在ClassCondition类中使用 metadata(注解元对象)获取注解定义的属性值,这里我们便需要从config的@ConditionOnClass注解中利用getName()方法获取其属性值 比如该例子:{value=[redis.clients.jedis.Jedis, com.alibaba.fastjson.JSON]} 然后通过key值“value”来获取map的值,之后强转成数组,利用forEach循环和反射机制,循环判断该数组中(即pom.xml中)有无对应的坐标依赖导入以此来控制true或false的输出,然后控制Config类中标识该注解的Bean的生成,这便是动态的添加全类名以判断pom.xml坐标中是否加入对应的依赖,这也是SpringBoot通过pom.xml判断是都存在相关依赖来加载相应的Bean

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值