Spring源码解读 --- 重要注解组件

it2026-08-24  4

(一)@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 ------"); } }
最新回复(0)