SpringBoot Bean被加载时进行控制
零维展开智子 人气:0序章
简介:bean的加载控制指根据特定情况对bean进行选择性加载以达到适用项目的目标。
根据之前对bean加载的八种方式,其中后面四种是可以对bean被加载时进行控制。
我拿第六种来举个例子。
之前也举过例子,但是实际开发呢,一般不会那么使用。
import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; public class MyImportSelector implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { try { Class<?> name = Class.forName("yi.beans.kun"); if (name!=null){ return new String[]{"yi.beans.Cat"}; } }catch (ClassNotFoundException e){ return new String[0]; } return null; } }
通过查看某个类是否存在来控制是否加载目标类。
这个类我是不存在的。
import org.springframework.context.annotation.Import; import yi.beans.MyImportSelector; @Import(MyImportSelector.class) public class AConfig { }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.config.AConfig; public class App3 { public static void main(String[] args) { ApplicationContext context=new AnnotationConfigApplicationContext(AConfig.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
所以我是没有加载这个bean的,还是老话,前面的那些暂时不看。
加载控制@Conditional派生注解
到了这里,你的spring项目就该换成springboot项目了,pom.xml中添加坐标,我就不多说了,这就是springboot的注解,源代码中大量使用。
这是我未加控制前的代码
import org.springframework.context.annotation.ComponentScan; @ComponentScan("yi.beans") public class AConfig { }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import yi.config.AConfig; public class App3 { public static void main(String[] args) { ApplicationContext context=new AnnotationConfigApplicationContext(AConfig.class); String[] names = context.getBeanDefinitionNames(); for (String name : names) { System.out.println(name); } } }
有猫,有狗,有老鼠,只不过我给他们都起了名字,你们很容易就会看出来。
现在我要对猫这个bean在创建时加一控制。
控制后
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication; import org.springframework.stereotype.Component; @ConditionalOnClass(Mouse.class) //要加载猫,必须要有老鼠这个bean @ConditionalOnBean(name = "zhizhi") //而且这个老鼠bean的名字必须是“zhizhi” @ConditionalOnMissingClass("yi.beans.Dog") //但是不能有狗,猫捉老鼠不想有狗 @ConditionalOnNotWebApplication //环境必须为非Web环境 @Component("miao") //猫的bean叫“miao” @Data @NoArgsConstructor @AllArgsConstructor public class Cat { String shout; }
这里我加了几个常见的派生注解,其他的代码都是不用变的,我的bean里卖虽然有一个叫做“zhizhi”的老鼠,但是有狗,所以猫是加载不出来的。
其中的
@ConditionalOnClass
@ConditionalOnBean
这两个注解非常相似,一般就用上面那个控制类的字节码或者路径。下面那个获取bean的名字,搭配使用就好了。
bean依赖的属性配置
先定义两个最基础的bean
import lombok.Data; @Data public class Mouse { private String name; private int age; }
import lombok.Data; @Data public class Cat { private String name; private int age; }
cartoon:
cat:
name: "图多盖洛"
age: 5
mouse:
name: "泰菲"
age: 1
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @Data @ConfigurationProperties(prefix = "cartoon") public class CartoonProperties { private Cat cat; private Mouse mouse; }
import lombok.Data; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; @Data @Component @EnableConfigurationProperties(CartoonProperties.class) public class CartoonCatAndMouse { private Cat cat; private Mouse mouse; private CartoonProperties cartoonProperties; public CartoonCatAndMouse(CartoonProperties cartoonProperties){ this.cartoonProperties=cartoonProperties; this.cat=new Cat(); this.cat.setName(cartoonProperties.getCat()!=null&& StringUtils.hasText(cartoonProperties.getCat().getName())? cartoonProperties.getCat().getName():"Tom"); this.cat.setAge(cartoonProperties.getCat()!=null&& cartoonProperties.getCat().getAge()!=0? cartoonProperties.getCat().getAge():6); this.mouse=new Mouse(); this.mouse.setName(cartoonProperties.getMouse()!=null&&StringUtils.hasText(cartoonProperties.getMouse().getName())? cartoonProperties.getMouse().getName():"Jerry"); this.mouse.setAge(cartoonProperties.getMouse()!=null && cartoonProperties.getMouse().getAge()!=0? cartoonProperties.getMouse().getAge():2); } public void play() { System.out.println(cat.getAge()+"岁的"+cat.getName()+"和"+mouse.getAge()+"岁的"+mouse.getName()+"打起来了"); } }
import com.yi.bean.CartoonCatAndMouse; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class SpringbootBean2ApplicationTests { @Autowired private CartoonCatAndMouse cartoonCatAndMouse; @Test void contextLoads() { cartoonCatAndMouse.play(); } }
可以看到加载的就是我们自己写的配置,现在我把配置注解一部分,我们再来看运行结果。
cartoon:
cat:
# name: "图多盖洛"
age: 5
mouse:
# name: "泰菲"
age: 1
可以看到,没有写的属性使用的就是默认属性,也就是自动配置的思想,只有在调用的时候才会生成bean,默认的bean也不会在项目加载时就添加,这样压力会很大。如果我们没有使用某个第三方的bean,我们的项目启动时也并不会加载默认的bean。
加载全部内容