该接口其实是 BeanFactoryPostProcessor 接口的一个衍生子类,除了父类提供的 postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 获取 BeanFactory 对象的方法,子类还扩充了一个可以获取 postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) 注册器的方法。有了 BeanFactory 工厂和 BeanDefinitionRegistry 注册器你就可以在对象实例化之前做很多事情(修改某个类中的属性值、添加或者删除 BeanDefinition 等)
我们先定义一个类 Apple,代码如下
public class Apple {
}
然后要讲这个类交给 Spring 管理,也就是将这个类放到 Spring 的单例缓冲池中,这里借助 BeanDefinitionRegistryPostProcessor 接口来实现这需求,这里首先通过 postProcessBeanDefinitionRegistry() 方法,我们可以拿到注册器,注册器就会把 BeanDefinition 往 BeanFactory 加工厂中注册。 代码如下:
@Component
public class MyConfigurationPostProcessor1 implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {// 直接手动 new 一个 GenericBeanDefinition,因为 Spring 会根据 BeanDefinition // 帮我们生产 bean 实例GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();genericBeanDefinition.setBeanClass(ProcessorEntity.class);// 然后再将 BeanDefinition 注册到 BeanFactory 容器中isterBeanDefinition("processorEntity",genericBeanDefinition);}
}
这个方法就是通过自己去创建 BeanDefinition 模版,然后将这个模版交给了 Spring 管理,就可以帮我们生产处我们想要的 ProcessorEntity 对象。那么我们不想这样干,可不可以不定义 BeanDefinition 就直接注册的到 Spring 容器(其实就是 BeanFactory 容器中)中呢。绝对可以的,看下面操作。
依旧是借助 BeanDefinitionRegistryPostProcessor 接口,只不过这次借助 postProcessBeanFactory() 方法,我们可以在这个方法中获取到 BeanFactory,直接往通过这个 BeanFactory 暴露的 API 往容器中扔对象。
BeanFactory 工厂就提供了很多的方法给我们做 CRUD 操作了。
@Component
public class MyConfigurationPostProcessor1 implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// 获取到默认工厂 DefaultListableBeanFactory 啥都好办兄弟// 接口 ConfigurableListableBeanFactory 方法太少了,强转成 DefaultListableBeanFactoryDefaultListableBeanFactory beanFactory = (BeanFactory();// 直接通过手动方式将类交给 Spring 管理isterSingleton("apple", new Apple());// 删除一、二、三级缓冲池中创建好的实例 bean// beanFactory.destroySingleton("apple");}@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {// 直接手动 new 一个 GenericBeanDefinition,因为 Spring 会根据 BeanDefinition // 帮我们生产 bean 实例GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();genericBeanDefinition.setBeanClass(ProcessorEntity.class);// 然后再将 BeanDefinition 注册到 BeanFactory 容器中isterBeanDefinition("processorEntity",genericBeanDefinition);}
}
BeanFactory 因为接口中方法比较少,所以我们可以通过他的子类来获取更多的 API 操作,第一时间想到的必须是默认工厂 DefaultListableBeanFactory。最终通过调用 getBean(Apple.class) 是可以获取到 Apple 实例的。
这个其实类似于上面的 BeanFactory 直接注册,只不过不需要去实现 BeanDefinitionRegistryPostProcessor 接口而已。代码如下:
public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class);// 获取到默认工厂 DefaultListableBeanFactory 啥都好办兄弟// 接口 ApplicationContext 方法太少了DefaultListableBeanFactory beanFactory = (BeanFactory();// 直接通过手动方式将类交给 Spring 管理isterSingleton("apple", new Apple());Apple apple = Bean(Apple.class);System.out.println("apple = " + apple);// 删除一、二、三级缓冲池中创建好的实例 bean// beanFactory.destroySingleton("apple");}
最终通过调用 getBean(Apple.class) 是可以获取到 Apple 实例的。
定义一个不带 @Component 而且不被 @ComponentScan 扫描到的实体类,如下:
public class Blue {
}
然后通过 @Bean 注解将上面的实体交给 Spring 管理,如下:
@BeansScanner(basePackage = "com.gwm.scan.beans")
public class TestBean {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class);Blue blue = Bean(Blue.class);System.out.println("blue = " + blue);}@Beanpublic Blue blue() {System.out.println("======>");return new Blue();}
}
这种方法的原理其实很简单,就是 Spring 通过反射调用 @Bean 修饰的方法,然后将他返回的结果注册到了 Spring 容器中而已。
代码如下:
public class Dog {
}@Component
public class DogAware implements BeanFactoryAware {@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {DefaultListableBeanFactory factory = (DefaultListableBeanFactory)isterSingleton("dog",new Dog());}
}@ComponentScan
public class BeanAwareDemo {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanAwareDemo.class);Dog dog = Bean(Dog.class);System.out.println("dog = " + dog);}
}
这个其实本质还是通过获取到 BeanFactory 工厂直接将 Dog 交给 Spring 管理
FactoryBean 是 Spring 中留个开发很好扩展并且自定义实例的一个机会,MyBatis 框架就利用这个接口完美整合
代码实例:
@Component
public class MyDogFactoryBean implements FactoryBean<Dog> {@Overridepublic Dog getObject() throws Exception {return new Dog();}@Overridepublic Class<?> getObjectType() {return Dog.class;}
}
这里需要注意以下三点:
1、beanName=&myDogFactoryBean 表示获取到的是 MyDogFactoryBean 类的实例,如果 beanName=myDogFactoryBean 表示获取到的是 Dog 类的实例。
2、只有使用到了 Dog 类才会触发 MyDogFactoryBean 类调用 getObject() 方法,有点懒加载的感觉。
3、MyDogFactoryBean 类实例存储在单例缓冲池中,Dog 类实例存在 FactoryBeanObjectCache 缓存中。
@Import
可以用来导入第三方的提供的类,它有三种用法:
1、@Import(Apple.class) 直接导入 Apple 类,如下:
public class Apple {
}@Configuration
@Import(Apple.class)
public class MainConfig {}
2、@Import(AppleImportSelector.class) 通过实现接口 ImportSelector 来间接导入 Apple 类,如下:
public class Apple {
}public class AppleImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{Name()};}
}@Configuration
@Import(AppleImportSelector.class)
public class MainConfig {}
3、@Import(AppleImportBeanDefinitionRegistrar.class) 通过实现接口 ImportBeanDefinitionRegistrar 来间接导入 Apple 类,如下:
public class Apple {
}public class AppleImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();genericBeanDefinition.setBeanClass(Apple.class);isterBeanDefinition("apple",genericBeanDefinition);}
}@Configuration
@Import(AppleImportBeanDefinitionRegistrar.class)
public class MainConfig {}
本文发布于:2024-01-30 14:51:45,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170659750620792.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |