目录
1.@Scope 设置组件作用域
singleton 默认值单例,在IOC容器启动的时候就创建了,只会创建一个
prototype 多实例,调用一次创建一次
配置类:
@Configuration
public class MainConfig {
@Scope("prototype")
@Bean(value = "user")
public User user(){
System.out.println("加载了...."); //这个可以用来测试容器的创建时机,单例的时候,在没有调用,但是容器启动了就会打印这个结果(总共只有一次),而多例是在调用一次就打一次。
return new User("vison",23);
}
}
测试类:
public class TestAnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
User user1 = configApplicationContext.getBean(User.class);
User user2 = configApplicationContext.getBean(User.class);
System.out.println(user1==user2); //这里是false
}
}
如上两个测试类:当scope为prototype时候,那么产生的bean是多例的,所以测试的结果就是false;
当scope为singleton时候,那么产生的bean是单例的,上面的结果就应该是true。
注意点:
单例的bean的创建在容器启动的时候就创建好了,而多例是在调用一次才创建一次。
2. @Lazy bean的懒加载
单例bean :默认在容器启动的时候创建对象
懒加载:容器启动的时候不加载对象,第一次使用(获取)bean创建对象,并初始化
配置类:
@Configuration
public class MainConfig {
@Lazy
@Bean(value = "user")
public User user(){
System.out.println("加载了....");
return new User("vison",23);
}
}
测试类:
public class TestAnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
/* User user2 = configApplicationContext.getBean(User.class);
System.out.println(user1);*/
}
}
如上面的测试,使用了@Lazy注解;当加载了IOC容器,user对象并不会创建,“加载了.....”不会打印,当打开下面的注释就会打印出来;如果去掉@Lazy注解,当加载IOC容器的时候,user对象就已经创建出来了,那么“加载了.....”会即刻打印出来。这就是懒加载。
3.@Conditional 按照条件注册bean
按照一定条件进行判断,满足条件就给IOC容器注册bean
作用在类上表示只有满足当前条件才会让当前类实例化,类中的方法才会可以使用
先看@Conditional源码:
@Target({ElementType.TYPE, ElementType.METHOD}) //可以作用于类上或者方法上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
Class<? extends Condition>[] value(); //这个表示参数是需要继承Condition的Class类型
}
在window环境下创建bean
例子1:
1. 创建一个条件的类
public class WindowsCondition implements Condition {
//conditionContext 判断条件能使用的上下文
//annotatedTypeMetadata 注释信息
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//能获取到ioc使用到的beanFactory
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
//获取到类加载器
ClassLoader classLoader = conditionContext.getClassLoader();
//获取到当前的环境,包括JVM等
Environment environment = conditionContext.getEnvironment();
//获取到bean定义注册类,所有的bean注册,查询,移出都是在BeanDefinitionRegistry中
BeanDefinitionRegistry registry = conditionContext.getRegistry();
ResourceLoader resourceLoader = conditionContext.getResourceLoader();
String property = environment.getProperty("os.name");
if (property.contains("Window")){
return true;
}
return false;
}
}
2.同理可以创建一个LinuxCondition实现Condition接口的条件类
3.配置类
@Configuration
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
@Conditional(WindowsCondition.class)
@Bean(value = "windowUser")
public User user02(){
return new User("vison02",23);
}
@Conditional(LinuxCondition.class)
@Bean(value = "LinuxUser")
public User user03(){
return new User("vison03",23);
}
}
4.测试类
public class TestAnotation {
public static void main(String[] args) {
AnnotationConfigApplicationContext configApplicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
String[] beanNames = configApplicationContext.getBeanNamesForType(User.class);
for (String bean : beanNames){
System.out.println(bean);
}
}
}
如果当前环境时window的话,结果只有 user01 和 windowUser 。
例子2:
上面例子把条件放在类上
@Conditional(WindowsCondition.class)
@Configuration
public class MainConfig {
@Bean(value = "user01")
public User user01(){
return new User("vison01",23);
}
@Bean(value = "user02")
public User user02(){
return new User("vison02",23);
}
@Bean(value = "user03")
public User user03(){
return new User("vison03",23);
}
}
这个表示只有满足上面的条件后才会注册这个配置中所有的bean,这里只有满足windowsCondition条件(window环境下)才会创建里面的user对象。反之其他环境一个bean都会注册。