文章目录
注册bean的用法
1、通过ImportBeanDefinitionRegistrar注册bean简单用法
目标对象Car
public class Car {
}
编写ImportBeanDefinitionRegistrar的实现类SimpleRegistry
public class SimpleRegistry implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName("com.example.demo.registry.Car");
registry.registerBeanDefinition("car", beanDefinition);
}
}
启动类上加@Import(SimpleRegistry.class)
@Import(SimpleRegistry.class)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
Object bean = run.getBean(Car.class);
System.out.println(bean);
}
}
2、通过ImportBeanDefinitionRegistrar使用自定义注解注册bean复杂用法
创建过滤注解RegistryAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface RegistryAnnotation {
}
在目标对象Car上加上注解@RegistryAnnotation
@RegistryAnnotation
public class Car {
}
编写ImportBeanDefinitionRegistrar的实现类SimpleRegistry
public class HardRegistry implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//创建对象,参数true代表使用默认过滤规则,例如@component注解,false代表使用自己定义的使用注解的过滤规则
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);
scanner.addIncludeFilter(new TypeFilter() {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//如果这个类添加了@RegistryAnnotation注解就添加到容器中
return metadataReader.getAnnotationMetadata().hasAnnotation("com.example.demo.registry.RegistryAnnotation");
}
});
//扫描目标对象Car所在的包
scanner.scan("com.example.demo.registry");
}
}
启动类上加@Import(HardRegistry.class)
//@Import(SimpleRegistry.class)
@Import(HardRegistry.class)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
Object bean = run.getBean(Car.class);
System.out.println(bean);
}
}
3、通过FactoryBean创建普通对象注册bean简单用法
目标对象Bike
public class Bike {
private int height;
public Bike(int height) {
this.height = height;
}
}
创建FactoryBean的实现类SimpleFactoryBean ,让spring容器通过它来实现普通对象的创建
public class SimpleFactoryBean implements FactoryBean<Bike> {
@Override
public Bike getObject() throws Exception {
Bike bike = new Bike(1);
return bike;
}
@Override
public Class<?> getObjectType() {
return Bike.class;
}
}
启动类配置SimpleFactoryBean 把对象装载到spring容器
//@Import(SimpleRegistry.class)
//@Import(HardRegistry.class)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
Object bean = run.getBean(Bike.class);
System.out.println(bean);
}
@Bean
public SimpleFactoryBean bikeFactoryBean() {
SimpleFactoryBean simpleFactoryBean = new SimpleFactoryBean();
return simpleFactoryBean;
}
}
4、通过FactoryBean创建可以生成任意接口的动态代理对象注册bean复杂用法
定义接口
public interface Transport {
void getAllTransport();
}
创建FactoryBean的实现类HardFactoryBean ,让spring容器通过它来实现可以生成任意接口的动态代理对象
public class HardFactoryBean implements FactoryBean {
private Class clazz;
public HardFactoryBean(Class clazz) {
this.clazz = clazz;
}
@Override
public Object getObject() throws Exception {
Object proxyInstance = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if ("getAllTransport".equals(method.getName())) {
System.out.println(clazz + "的动态代理对象的getAllTransport方法被执行了");
}
return null;
}
});
return proxyInstance;
}
@Override
public Class<?> getObjectType() {
return clazz;
}
}
启动类配置HardFactoryBean 把对象装载到spring容器
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
Object bean = run.getBean(Transport.class);
Transport transport = (Transport) bean;
transport.getAllTransport();
}
@Bean
public HardFactoryBean transportFactoryBean() {
HardFactoryBean simpleFactoryBean = new HardFactoryBean(Transport.class);
return simpleFactoryBean;
}
}
通过自定义注解和生成任意接口的动态代理对象注册bean模拟mybatis数据层用法
步骤一:创建过滤注解FinalAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FinalAnnotation {
}
步骤二:在目标接口上加上注解@FinalAnnotation
@FinalAnnotation
public interface FinalMapper {
void select();
}
步骤三:创建ClassPathBeanDefinitionScanner的子类MyMapperScanner重写isCandidateComponent()方法来让扫描器接受接口类型
public class MyMapperScanner extends ClassPathBeanDefinitionScanner {
public MyMapperScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
super(registry, useDefaultFilters);
}
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
AnnotationMetadata metadata = beanDefinition.getMetadata();
return metadata.isInterface();
}
}
补充:通过阅读new ClassPathBeanDefinitionScanner().scan()源码可知扫描器不接受目标对象是接口的bean,因此需要子类重写isCandidateComponent()方法
步骤四:创建FactoryBean的实现类FinalFactoryBean ,让spring容器通过它来实现可以生成任意接口的动态代理对象
public class FinalFactoryBean implements FactoryBean {
private Class clazz;
public FinalFactoryBean(Class clazz) {
this.clazz = clazz;
}
@Override
public Object getObject() throws Exception {
Object instance = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
if ("select".equals(method.getName())) {
System.out.println(clazz + "的动态代理对象的select()方法被执行了");
}
return null;
}
});
return instance;
}
@Override
public Class<?> getObjectType() {
return clazz;
}
}
步骤五:把接口注册到bean显然是不行的,所以需要类型转换,转换FinalFactoryBean的BeanDefinition进行注册
public class FinalRegistry implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
MyMapperScanner scanner = new MyMapperScanner(registry, false);
// ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);
scanner.addIncludeFilter(new TypeFilter() {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
return metadataReader.getAnnotationMetadata().hasAnnotation("com.example.demo.registry.finalRegistry.FinallyAnnotation");
}
});
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents("com.example.demo.registry.finalRegistry");
for (BeanDefinition beanDefinition: candidateComponents){
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FinalFactoryBean.class);
builder.addConstructorArgValue(beanDefinition.getBeanClassName());
AbstractBeanDefinition factoryBeanDefinition = builder.getBeanDefinition();
registry.registerBeanDefinition(beanDefinition.getBeanClassName(), factoryBeanDefinition);
}
// scanner.scan("com.example.demo.registry.finalRegistry");
}
}
步骤六:
启动类配置HardFactoryBean 把对象装载到spring容器,使用@Import注解注入Registrar
@Import(FinalRegistry.class)
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(DemoApplication.class, args);
Object bean = run.getBean(FinalMapper.class);
FinalMapper mapper= (FinalMapper) bean;
mapper.select();
}
@Bean
public FinalFactoryBean finalFactoryBean() {
FinalFactoryBean finalFactoryBean = new FinalFactoryBean(FinalMapper.class);
return finalFactoryBean;
}
}