<返回更多

Springboot 对象实例是如何动态加载到 IOC 容器的

2022-10-10  今日头条  小技术酱
加入收藏

概念

IOC:控制反转。从前需要在程序中创建对象实例;现在则通过一个外部的容器统一动态创建

spring IOC 容器中的实例如何动态加载

Condition:只有在特定条件满足时才加载

举例

 

@ConditionalOnBean

当存在某个实例时才加载

@ConditionalOnClass

当存在某个字节码文件时才加载

@ConditionalOnProperty

当在配置文件中存在某项配置信息时才加载

将这些注解写在类或者方法上,就可以在程序运行时动态加载

 

自定义动态加载

  1. 实现Condition接口自定义筛选条件
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import JAVA.util.Map;

public class ClassCondition implements Condition {
    /**
        Condition接口只有一个matches方法
        context:上下文对象:环境对象、IOC容器对象,ClassLoader对象
        metadata:注解元对象:注解定义的属性值
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        try {
            //获取注解定义的属性值 “org.springframework.data.redis.core.RedisTemplate”
            Map<String, Object> map = metadata.getAnnotationAttributes(ConditionOnClass.class.getName());
            //加载字节码文件,如果可以加载则返回true,否则返回false
            String[] value = (String[]) map.get("value");
            for (String v : value) {
                Class<?> cls = Class.forName(v);
            }
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }
}
  1. 自定义注解
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();
}
  1. 创建User类用于测试
public class User {

}
  1. 创建加载User实例对象配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//说明这是一个配置类,在启动时会被加载
@Configuration
public class UserConfig {

    @Bean
    //该注解表示当“org.springframework.data.redis.core.RedisTemplate”存在时创建User实例对象
    @ConditionOnClass("org.springframework.data.redis.core.RedisTemplate")
    public User user(){
        return new User();
    }
}
  1. 测试
@SpringBootApplication
public class SpingbootConditionApplication {

    public static void main(String[] args) {
        //接收到加载的配置内容
        ConfigurableApplicationContext context = SpringApplication.run(SpingbootConditionApplication.class, args);
        Object user = context.getBean("user");
        //输出“com.study.boot.User@64469d8”表示已将user这个bean加载到容器
        System.out.println(user);
    }
}
声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>