@Lazy
懶加載模式
默認是單實例的,ioc容器啟動就會調用方法,并放在容器中,以后就從容器中拿,但是如果加了@Lazy注解時,容器啟動時不會去創建Bean,在第一次使用時才會創建Bean并初始化
Demo:
/**
* 懶加載:
* 單實例情況下,容器啟動不會去創建bean對象,在第一次使用的時候才會創建bean對象,并初始化
*
* */
@Lazy
//默認是單實例的,ioc容器啟動就會調用方法,并放在容器中,以后就從容器中拿
//如果改成多實例的話,ioc容器啟動時不會調用方法
@Scope("prototype") //singleton 是單實例的
//給容器注冊一個bean,類型是返回值,id默認是用方法名作為id
//當指定value時,value的值作為該bean的id,不會再去看方法名是什么了
@Bean(value = "person")
public Person person01(){
return new Person("snail",20);
}
@Conditional
按照一定的條件進行判斷,滿足條件給容器中注冊bean
1、需要實現org.springframework.context.annotation下的Condition接口,重寫Condition下的方法
Condition接口:
public interface Condition {
/**
* Determine if the condition matches.
* @param context the condition context
* @param metadata metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
* or {@link org.springframework.core.type.MethodMetadata method} being checked.
* @return {@code true} if the condition matches and the component can be registered
* or {@code false} to veto registration.
*/
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
比如實現該接口的一個小Demo:
public class WindowsCondition implements Condition {
/**
* ConditionContext:判斷條件能使用的上下文
* AnnotatedTypeMetadata:注釋信息
* */
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//獲取IOC中的beanfactory
ConfigurableListableBeanFactory beanFactory=context.getBeanFactory();
//獲取類加載器
ClassLoader classLoader=context.getClassLoader();
//獲取當前環境信息
Environment environment=context.getEnvironment();
//獲取bean的定義的注冊類
BeanDefinitionRegistry registry=context.getRegistry();
String env=environment.getProperty("os.name");
if (env.contains("Windows")){
return true;
}
else
return false;
}
}
2、在Bean注冊時加上注解@Conditional({實現接口的類名1.class,實現接口的類名2.class})
如下:
@Conditional({WindowsCondition.class})
@Bean(value="niuniu")
public Person person02(){
return new Person("牛牛",18);
}
@Import
標注在類上,并非方法上
可以直接快速注冊到容器中
@Import({color.class, MyImportSelector.class})
public class MainConfig2 {}
其中:color.class就是一個要注冊進來的Bean
@Import的ImportSelector方式
1、實現ImportSelector接口,最終返回要注冊是Bean
public class MyImportSelector implements ImportSelector {
/**
*
* @param importingClassMetadata
* @return 導入到組件中的類名
* AnnotationMetadata 標注了@Import的類上的所有注解
*
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.dwd.snail.testspring.test.bean.blue","com.dwd.snail.testspring.test.bean.yellow"};
}
}
2、在配置類中引用實現該接口的方法
@Import({color.class, MyImportSelector.class})
public class MainConfig2 {}
其中 MyImportSelector就是實現接口的方法
使用Spring的FactoryBean注冊
1、創建一個工廠Bean,實現FactoryBean接口
//創建一個工廠bean
public class ColorFactoryBean implements FactoryBean<color> {
//返回一個color對象,會添加到容器中
@Override
public color getObject() throws Exception {
return new color();
}
@Override
public Class<?> getObjectType() {
return color.class;
}
//是否單實例?單實例只會在容器中保存一份
@Override
public boolean isSingleton() {
return true;
}
}
2、注冊這個工廠Bean
@Bean
public ColorFactoryBean colorFactoryBean(){
return new ColorFactoryBean();
}
總結下給容器注冊Bean的方法:
/**
- 給容器中注冊組件
- 1、包掃描+組件標注注解(@Controler@Service@Repository@Component),僅限于本工程內,帶這些注解的bean自動注入
- 2、@Bean 用于未帶注解的或者第三方jar包中的bean注冊
- 3、@Import方式來導組件,在配置類中注解
- 4、@Import-ImportSelector來導入
- 5、使用Spring的FactoryBean(工廠bean)
- */