蚌埠网站建设公司,用fullpage做的网站,上海品牌战略咨询公司,做游戏攻略网站赚钱吗文章目录 1、编程式Bean加载控制2、注解式Bean加载控制3、Conditional派生注解4、Bean依赖的属性配置 Bean的加载控制指根据特定情况对bean进行选择性加载以达到适用于项目的目标 上篇Bean声明的方式中#xff0c;后4种可以实现对Bean加载的控制#xff0c;分别是#xff1a… 文章目录 1、编程式Bean加载控制2、注解式Bean加载控制3、Conditional派生注解4、Bean依赖的属性配置 Bean的加载控制指根据特定情况对bean进行选择性加载以达到适用于项目的目标 上篇Bean声明的方式中后4种可以实现对Bean加载的控制分别是
AnnotationConfigApplicationContext调用register方法Import导入ImportSelector接口Import导入ImportBeanDefinitionRegistrar接口Import导入BeanDefinitionRegistryPostProcessor接口
且上篇中已演示了部分对Bean加载的控制这里演示编程式和注解式两种。
1、编程式Bean加载控制
下面实现当A类被加载了我才将B类的Bean加载。
public class MyImportSelector implements ImportSelector {Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {try {Class? clazz Class.forName(com.plat.bean.Mouse);if(clazz ! null) { //如果老鼠的类被加载了注意不关心是不是Bean只看是不是类加载了return new String[]{com.itheima.bean.Cat}; //那就把猫这个类注册成Bean}} catch (ClassNotFoundException e) {//e.printStackException();return new String[0]; //条件类老鼠不存在时返回一个空数组}return null;}
}
2、注解式Bean加载控制
上面代码里的判断的逻辑对所有类都大同小异因此考虑抽成一组注解公共逻辑部分用AOP去实现就好。Spring提供了Conditional注解 注解的属性类型是一个Condition接口或者其子类且Condition接口有抽象方法需要实现这样写还是很繁琐。因此常使用Conditional注解的派生注解。注意很多派生注解都是SpringBoot的。
!--非Boot项目记得导入SpringBoot的起步依赖才能找到这些派生注解--
dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId version2.5.4/version
/dependency
!--注意boot的starter包含Spring的一些依赖比如spring-context若旧项目是Spring项目可直接注释掉相关依赖省的依赖冲突版本混乱--以下分别整理这些派生注解。
3、Conditional派生注解 ConditionalOnClass有这个类了是不是Bean无所谓就加载下面这个Bean Component
ConditionalOnClass(Mouse.class)
public class Cat{}
//有老鼠这个类被加载了注意强调的是类不管你是不是Bean就加载Cat这个Bean使用注解的value属性这么写有点此地无银三百两了编译器报错的时候即导包失败就说明没这个类那还判断个啥所以常用name属性而不是直接class
Component
ConditionalOnClass(name com.plat.po.Mouse)
public class Cat{}ConditionalOnMissingClass没这个类时是不是Bean无所谓就加载下面这个Bean Component
ConditionalOnMissingClass(com.plat.po.Wolf) //没有狼来时加载猫成为一个Bean
public class Cat{}这样控制Bean加载的一个很经典的例子就是DataSource如下即只有用到了MySQL的驱动类时再加载dataSource的Bean
public class SpringConfig {BeanConditionalOnClass(name com.mysql.jdbc.Driver)public DruidDataSource dataSource(){DruidDataSource ds new DruidDataSource();return ds;}
}
再往大了想有一个技术框架的jar包当你用到某个标志类那就加载该技术所有的Bean否则就不加载此时使用者只需做一些简单的配置即可。 ConditionalOnBean 有这个Bean时才加载下面的这个Bean public class SpringConfig {BeanConditionalOnBean(namejerry)ConditionalOnMissingBean(name com.plat.po.Dog)public Cat tom(){return new Cat();}
}//不关心有没有老鼠的类被加载而是要求有叫杰瑞的Bean且没有狗的BeanTom才加载到Ioc中成为BeanConditionalOnNotWebApplication和ConditionalOnWebApplication 非Web或者Web环境下再加载 注意这些派生注解同时出现在同一个类上方时它们之间是且的关系。
4、Bean依赖的属性配置 结论当业务Bean运行需要一些属性时抽取一个独立的属性类xxProperties读取配置文件信息 用一个循序渐进的示例来体验属性配置先准备几个demo类
Data
public class Cat{private String name;private Integer age;
}Data
public class Mouse{private String name;private Integer age;
}//猫和老鼠卡通类
Component
public class CartoonCatAndMouse{private Cat cat;private Mouse mouse;//提供个构造方法给两个属性赋值不然默认null下面会空指针public CartoonCatAndMouse(){cat new Cat();cat.setName(tom);cat.setAge(3);mouse new Mouse();mouse.setName(jerry);mouse.setAge(3);}public void play(){System.out.println(cat.getAge()岁的cat.getName()与mouse.getAge()岁的mouse.getName()打起来了);}
}//启动类中调用下play方法
SpringBootApplication
public class App{public static void main(String[] args){ConfigurableApplicationContext ctx pringApplication.run(app.class);CartoonCatAndMouse bean ctx.getBean(CartoonCatAndMouse.class);bean.play();}
}此时配置都硬编码了显然不合理。 优化第一步引入yaml配置并ConfigurationProperties读取 cartoon:cat:name: tomage: 3mouse:name: jerryage: 4Component
ConfigurationProperties(prefix cartoon)
//加个set不然cat属性和mouse属性为null
Data
public class CartoonCatAndMouse{private Cat cat;private Mouse mouse;public void play(){System.out.println(cat.getAge()岁的cat.getName()与mouse.getAge()岁的mouse.getName()打起来了);}
}此时如果yaml配置中没有相关配置则对应的对象为null进而空指针。也就是说一加ConfigurationProperties(prefix “cartoon”)我的类和yaml配置绑死了没配置类都受影响。 优化第二步引入独立配置类CartoonProperties ConfigurationProperties(prefix cartoon)
Data
//旧知识点读取yaml的类的对象必须受Spring容器管控否则即使拿到yaml值也无法set给你
Component
public class CartoonProperties {private Cat cat;private Mouse mouse;
}
Component
Data
public class CartoonCatAndMouse{private Cat cat;private Mouse mouse;//构造器注入了用Autowired也行private CartoonProperties cartoonProperties;public void play(CartoonProperties cartoonProperties){this.cartoonProperties cartoonProperties;cat new Cat();cat.setName(cartoonProperties.getCat()!null StringUtils.hasText(cartoonProperties.getCat().getName())?cartoonProperties.getCat().getName():tom); //有则用无则用默认值//Mouse对象同样写法略System.out.println(cat.getAge()岁的cat.getName()与mouse.getAge()岁的mouse.getName()打起来了);}
}此时有个缺点CartoonProperties类不管用不用都被强制加载成一个Bean了但去掉Component只留ConfigurationProperties语法错误 ⇒ 用EnableConfigurationProperties 优化第三步EnableConfigurationProperties改掉强制加载Bean ConfigurationProperties(prefix cartoon)
Data
public class CartoonProperties {private Cat cat;private Mouse mouse;
}
ConfigurationProperties和EnableConfigurationProperties前者是做属性绑定的后者是开启属性绑定并设定对应的目标是谁
Component //这个Component也可以去掉用的时候Import(CartoonCatAndMouse.class)
Data
//即当我加载CartoonCatAndMouse时就用CartoonProperties.class并把CartoonProperties类加载成Bean
EnableConfigurationPropertiesCartoonProperties.class)
public class CartoonCatAndMouse{private Cat cat;private Mouse mouse;//重复代码略....这套模式的亮点有以下几个
合理的加载配置文件即你配置了就用你的没配就用默认值来工作对于属性类xxxProperties不用强制配置成Bean使用EnableConfigurationProperties对于业务功能的Bean通常使用Import将一个类加载成Bean来解耦强制加载Bean以降低Spring容器管理Bean的工作量以及强度