1.@Configuration + @Bean
【比xml配置而言类更好维护、分类和管理阅读】 代理
1.1@Configuration的类就成为了"配置类",【取代application.xml文件】 @Configuration(proxyBeanMethods=true)默认单例,false获取到对象每次不同
总结:
Spring 会创建CGLIB 代理,保证 @Bean 方法互相调用时,永远返回同一个单例 Bean。
1.2方法public User getName()上加上@Bean注解【@Bean(name="abc")】对象为abc,无name属性值,则对象为getName方法名 [取代application.xml中的
总结:
- 首选
name或value属性 :如果写了@Bean(name="abc"),Bean 的唯一标识就是abc。- 默认使用方法名 :如果没有指定
name,Spring 会直接取方法名getName作为 Bean 的 ID- 用来替代传统的
配置
2.@Import() 导入组件
底层是一个接口 ()里面的参数是: Class [] value() 【把 普通类 / 配置类 / ImportSelector 导入到spring的IOC容器中去,导入之后我们就可以直接从容器中拿】
特点:常用于第三方类、自动配置
@Configuration
@Import(User.class, OrderConfig.class) // 直接导入多个组件 public class AppConfig {}
3.@ImportResource()导入资源文件( 老xml配置文件 )
作用:把传统 xml 配置文件加载进 Spring
场景:兼容老项目、遗留 XML
@Configuration
@ImportResource("classpath:spring-context.xml") public class XmlConfig {}
4.@ConditionalOnBean() 条件装配
作用: 容器里有某个 Bean 时,才创建当前 Bean
@Configuration
public class ConditionConfig {
@Bean @ConditionalOnBean(User.class) // 有User才注册Order public Order order() { return new Order(); }
}
5.前四个注解大致总结:
@Import / @ImportResource / @Conditional 系列注解
都属于「配置类专用注解」,必须标注在 @Configuration 类上才会生效!
6.@ConfigurationProperties
作用:配置绑定 [自动把 application.yml / application.properties 里的配置项批量注入到 JavaBeanJava 类的属性中。]
/
- 简单粗暴理解:把当前类丢到Ioc容器中去 */ @Component //表明当前类是一个组件 {只有在容器中的组件,才会拥有SpringBoot提供的强大功能,加注解放入容器} 不代理 @ConfigurationProperties(prefix = "car1") // 这个car1就是properties中配置的car对象的键值对,如:car1.brand=BYD car1.price=123 // 这样car需要的属性会和properties中的自动对应 @Data // 没有手Setter 方法,@ConfigurationProperties 无法把配置文件里的值注入到成员变量中。 public class Car { private String brand; private Integer price; }
ConfigurationProperties 的底层逻辑是通过 Java 反射调用 Setter 方法 (如 setBrand)来完成赋值的。如果类中只有私有属性而没有对应的 Setter,Car对象中属性值null
注意 :@ConfigurationProperties(prefix = "test.test1") 若找不到prefix前缀时,对象Car创建时bean名称改为:test.test1-cn.stylefeng.guns.tenant.modular.Cat #
- 类所在的包在
@SpringBootApplication的扫描路径下,否则@Component不会生效。
7.@Confinguration @Commponent 不同
- 用
@Component:如果这个类只是一个纯粹的 POJO 数据载体,或者仅仅是用来承载配置属性,不涉及复杂的 Bean 组装 。每次调用都会 new 一个新对象 ,单例直接失效!- 用
@Configuration:如果你打算在这个类里定义多个有依赖关系的@Bean(例如Bean A的创建需要调用Bean B的方法),则必须使用它 。是配置类 ,Spring 会创建CGLIB 代理 ,保证 @Bean 方法互相调用时,永远返回同一个单例 Bean。
不要迷惑单例原因?从 Spring 容器中获取已创建好的 Bean
@Configuration
public class MyConfig {
@Bean public User user() {
return new User();
}
@Bean public Order order() {
// 无论调用多少次 user(),永远返回同一个Bean return new Order(user());
} }
8.@EnableConfigurationProperties
理解: 当多个bean被@ConfigurationProperties()注解修饰,不愿再每个加@Component时,此注解就牛了
作用: 适合导入第三方配置,[第三方的配置没有用自动装配的相关注解,即没丢到IOC容器中,开发人员无法使用!此注解解决!!!]1、开启属性配置绑定功能( 如:例子中的绑定Car类的属性 )使 @ConfigurationProperties 注解生效!
2、把组件自动注册到容器中( 如:例子中的Car,用了这个注解就可以把Car丢到Ioc容器中去 )
注意:@EnableConfigurationProperties 本身作用1.使@ConfigurationProperties修饰的po类与XXX.properties动态绑定2.将po类交由IOC容器管理!!!
但是要明白:@EnableConfigurationProperties 本身的类的前提是在IOC容器中,不然Spring如何读取。故【@Configuration 常用 @Component也可以但不多,@Service等也可以,很少用罢了,违背spring的设计语义】
@Configuration
@EnableConfigurationProperties(Car.class) public class MyConfig {
private Integer price;
}
@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration public class ThreadPoolConfig
}
总结: @EnableConfigurationProperties 只关心所在的类是不是一个 Spring Bean(在 IOC 里)。但是呢 类似ThreadPoolConfig 内部有@Bean注解,会有调用出现。所以不可改为@Component 。
9.ImportSelector
Spring 中用于 动态、条件化导入配置类 的核心接口
Spring Boot 自动配置(@EnableAutoConfiguration) 的底层灵魂
与 @
Import 对比
- 静态
@Import(XXX.class):编译时就写死要导入的类。ImportSelector:运行时 通过代码逻辑(判断环境、配置、类存在与否)动态决定导入哪些类。package org.springframework.context.annotation;public interface ImportSelector {
/ * 核心方法:返回需要导入的类的全限定名数组 * @param importingClassMetadata 被@Import标注的类的所有注解信息(可读取注解属性) * @return 要导入的@Configuration类/组件的全类名数组 */ String[] selectImports(AnnotationMetadata importingClassMetadata);}
执行时机(非常重要)
selectImports方法在 Spring 容器启动、Bean 实例化之前 被调用。
- 时机:早于
@Bean、@ComponentScan- 作用:决定哪些类会被注册成 BeanDefinition ,进而实例化为 Bean
- 当 Spring 解析到
@Import(YourSelector.class)注解时,会立即 实例化YourSelector并调用其selectImports()方法。- 特点 :它的执行优先级非常高,发生在处理当前配置类中的
@Bean、@ImportResource等其他注解之前 。因此,在selectImports()方法中,你无法感知到由@Bean定义的 Bean。
DeferredImportSelector后执行 接口方式 【主要用于动态获取bean @Import注解场景】
两者区别:
@Bean 定义的 Bean。 可以感知所有已加载的 Bean 定义和配置。 主要用途 根据简单条件(如注解属性)动态导入配置。 根据完整的上下文信息(如某个 Bean 是否存在)进行更复杂的动态导入。 排序支持 不支持。 支持通过
@Order 或
Ordered 接口排序。
3.1.//定义实现类实现接口ImportSelector
public class MyImportSelector implements DeferredImportSelector ;
}
}//注意:String[] selectImports 方法内可以根据开发者逻辑返回不同类的全限定名!!
3.2//在配置类上导入实现类
@Configuration @Import(MyImportSelector.class) public class MyConfiguration { @Bean
public Object test() { log.info("MyConfiguration create a object bean..."); return new Object(); }
}
3.3配置类样式
@Slf4j public class MyConfiguration3 {
public MyConfiguration3() { log.info("MyConfiguration3 construct..."); } public void execute() { log.info("MyConfiguration3 execute..."); }
} 3.4 调用 @SpringBootApplication public class XXApplication }
- MyConfiguration create a object bean…
- MyConfiguration1 construct…
- MyConfiguration2 construct…
- MyConfiguration3 construct…
- MyConfiguration3 execute…
原因:Spring 首先解析 MyConfiguration 类。虽然发现了 @Import,但因为它是 DeferredImportSelector,Spring 会先搁置它,转而去注册当前类中定义的 test() Bean。因此,@Bean 方法会最先执行。
类似场景:ImportBeanDefinitionRegistrar 接口方式 [定义注册器]
#扩展:AnnotationMetadata这个类 [做一个分布式任务调度的框架,如果结合springboot,那么在做一些自定义配置的时候就好很多]
1.定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(MyHttpDeferredImportSelector.class)
public @interface MyHttp {
String name() default "";
String value() default "";
}
2.注解实现类
@Slf4j
public class MyHttpDeferredImportSelector implements DeferredImportSelector ,v:{}",k,String.valueOf(v));
});
return new String[0];
}//结果 MyConfiguration1全类名, name:myc1, MyConfiguration1全类名, value:myc1-value
}
3.使用注解
@Slf4j
@MyHttp(name = "myc1",value = "myc1-value")
public class MyConfiguration1
public void execute()
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/259934.html