springBoot之自定义bean的注册方式

注册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;
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值