(一)@Conditional
- 用在方法上:按照一定的条件进行判断,满足条件给容器中注册bean。
- 用在类上:按照一定的条件进行判断,满足条件才会加载这个类中的所有信息。
@Conditional(WindowCondition.class)
@Bean("maotao")
public Person test01() {
return new Person("毛涛",21);
}
// 判断条件
public class WindowCondition implements Condition {
/**
*
* @param conditionContext 条件上下文
* @param annotatedTypeMetadata 注解信息
* @return
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
// 可以使用的组件
ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
ClassLoader classLoader = conditionContext.getClassLoader();
BeanDefinitionRegistry registry = conditionContext.getRegistry();
ResourceLoader resourceLoader = conditionContext.getResourceLoader();
Environment environment = conditionContext.getEnvironment();
// 获取操作系统名称
String environmentName = environment.getProperty("os.name");
// 判断容器中是否有bean,也可以注册bean
boolean zhangsan = registry.containsBeanDefinition("zhangsan");
if (!zhangsan) {
System.out.println("容器中没有张三");
}else{
// 注册张三
//registry.registerBeanDefinition("zhangsan",new B);
}
// 判断环境变量
if (environmentName.contains("Windows")) {
return true;
}
return false;
}
(二)@Lazy
懒加载,将单例的bean实例化方式改为懒加载,只有在第一次调用时才加载。
@Lazy
@Bean("person")
public Person test(){
System.out.println("正在创建:::::");
return new Person("wagnsan",20);
}
(三)@Scope
Spring设置bean在IOC容器中的作用域,默认是单例。
// prototype :多实例
// singleton : 单实例
// request :同一次请求创建一个实例
// session : 同一个session创建一个实例
//@Scope(value = "prototype")
@Lazy
@Bean("person")
public Person test(){
System.out.println("正在创建:::::");
return new Person("wagnsan",20);
}
(四)@ComponentScan
指定要扫描的包。
-
value是指定要扫描的包路径。
-
使用includeFilters,需要更改useDefaultFilters=false,禁用默认的过滤。
-
type 是选择过滤类型。
-
ANNOTATION, 注解类型 ASSIGNABLE_TYPE,指定类型 ASPECTJ,ASPECTJ表达式 REGEX,正则表达式 CUSTOM;自定义类型
-
@ComponentScan(value = "com.mt",includeFilters = {
//@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})}, //注解类型
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyFilter.class})},//自定义注册类型
useDefaultFilters = false
)
// 自己定义的过滤条件 需要实现Spring的TypeFilter
public class MyFilter implements TypeFilter {
/**
*
* @param metadataReader 读取到当前正在扫描的类信息
* @param metadataReaderFactory 可以获取到其他任何类的信息
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// 获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// 获取当前正在扫描类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取类路径相关信息
Resource resource = metadataReader.getResource();
String className = classMetadata.getClassName();
System.out.println("->>>"+className);
return false;
}
}
(五)给容器中注册组件的方式
-
包扫描(@ComponentScan)+组件标注注解(@Controller/@Service/@Repository/@Component)[适用于自己写的类]
-
@Bean[导入的第三方包组件]
-
@Import[快速给容器中导入一个组件]
-
@Import (要导入到容器中的组件),容器中就会自动注册这个组件,id默认是组件的全类名。
-
ImportSelector 返回需要导入组件的全类名数组。
-
ImportBeanDefinitionRegistrar 自己注册beanDefinition.
直接在类上使用该注解,引入需要的组件。
方式一 @Import({Color.class, Red.class}) public class MainConfig2 {
方式二 @Import({Color.class, Red.class, MyImportSelector.class}) public class MainConfig2 {
// 自定义逻辑需要导入的组件。 public class MyImportSelector implements ImportSelector { /** * * @param annotationMetadata 当前标注@Improt注解的类的所有注解信息 * @return 返回值,就是导入到容器中的组件全类名 */ @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { return new String[]{"com.mt.domain.Blue","com.mt.domain.Yellow"}; } }
方式三 @Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class}) public class MainConfig2 {
// 自定义要注册的组件。 public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * * @param importingClassMetadata 当前类的注解信息 * @param registry BeanDefinitation注册类 所有需要添加到容器中的bean都需要在此注册 * 通过registry.registryregisterBeanDefinition手工注册。 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainRow.class); registry.registerBeanDefinition("RainRow",rootBeanDefinition); } }
-
-
使用Spring提供的FactoryBean (工厂bean)
-
默认获取的是工厂bean提供的getObject()方法创建的对象。
-
要获取工厂bean本身,我们需要给id前面加一个&。
-
// Spring 提供的FactoryBean(工厂bean)
public class ColorFactory implements FactoryBean<Color>{
@Override
public Color getObject() throws Exception {
return new Color();
}
@Override
public Class<?> getObjectType() {
return Color.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
/**
* 注册bean
*/
@Bean
public ColorFactory ColorFactory() {
return new ColorFactory();
}
@Test
public void test06() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig2.class);
Object colorFactory = applicationContext.getBean("ColorFactory");
System.out.println(colorFactory);// 返回的是getObject创建的Color对象
Object colorFactory = applicationContext.getBean("&ColorFactory");
System.out.println(colorFactory);// 返回的是ColorFactory对象
}
(六)bean的生命周期
实现自定义初始化和销毁:
- 指定初始化和销毁方法。
/**
* @ClassName: MainConfigLifeCycle
* @Description: bean生命周期的配置
* @Author: mao-tao
* @Date: 2020-10-21 18:38
* @Version: 1.0
* 容器管理bean的生命周期: 创建 -------- 初始化 ------- 销毁
* 我们可以自定义初始化和销毁方法。
* 构造(对象创建):
* 单实例:在容器启动时创建对象(默认)使用懒加载则与多实例一样。
* 多实例:在每次调用时创建对象。
* 初始化:
* 对象创建好,并赋值好,调用初始化方法。
* 销毁:
* 单实例,容器关闭时。
* 多实例,容器不会管理bean,不会调用销毁方法。
* 1)、指定初始化和销毁方法
* 使用@Bean的initMethod和destoryMethod指定。
**/
@Configuration
public class MainConfigLifeCycle {
//@Scope(value = "prototype")
//@Lazy
@Bean(value = "car",initMethod = "init",destroyMethod = "destroy")
public Car test01() {
return new Car();
}
}
// 自定义初始化和销毁方法
public class Car {
public Car(){
System.out.println("car ------ constructor ------");
}
public void init() {
System.out.println("car ------ init ------");
}
public void destroy() {
System.out.println("cr ------ destory ------");
}
}
- 实现接口方式
通过让bean实现InitializingBean(定义初始化逻辑)、DisposableBean(定义销毁逻辑)
public class Cat implements InitializingBean, DisposableBean {
public Cat() {
System.out.println("cat ------ contructor ------");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("cat ------ init ------");
}
@Override
public void destroy() throws Exception {
System.out.println("cat ------ destroy ------");
}
}