欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springboot自定义注解(二)

程序员文章站 2022-05-23 18:28:53
...

在springboot自定义注解(一)中,我们已经用AOP实现了自定义注解的简单日志功能,今天我们来使用自定义注解实现bean的实例化。

第一步:自定义注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented

@Import({MyBeanDefinitionRegistrar.class})
public @interface MyFirstAnnotation {

    String name() default "";

    int age() default 0;
}

对比springboot自定义注解(一)中的自定义注解,可以发现多了@Import({MyBeanDefinitionRegistrar.class}) ,我们可以先将其理解为对注解进行处理的类,当然了,我们这里的处理就是利用注解进行bean的实例化。

第二步: 注解处理类

public class MyBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MyFirstAnnotation.class.getName()));
        String name = attributes.getString("name");
        int age = attributes.getNumber("age");

        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(Person.class);
        beanDefinition.getPropertyValues().add("name", name);
        beanDefinition.getPropertyValues().add("age", age);
        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, "person");
        BeanDefinitionReaderUtils.registerBeanDefinition(holder,registry);
    }
}

其实这个类的作用很单纯,我们可以理解其功能就是可以根据注解参数来注册BeanDefinition,该类实现了ImportBeanDefinitionRegistrar 接口,该接口只有一个方法:

/*Interface to be implemented by types that register additional bean definitions when processing @{@link Configuration} classes.*/
public interface ImportBeanDefinitionRegistrar {
    public void registerBeanDefinitions(
            AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}

通过@Import 引入接口ImportBeanDefinitionRegistrar的实现类MyBeanDefinitionRegistrar之后,registerBeanDefinitions 方法会被调用,在该方法中我们读取到注解参数,并用这些参数的值注册了一个BeanDefinition ,spring会将所有的BeanDefinition 进行实例化,我们这里实例化了一个Person对象,它有name和age两个属性。
第三步:自定义注解的使用

@MyFirstAnnotation(name = "ty", age = 26)
public class MyController {
    @Resource
    private Person person;

    @RequestMapping(value = "/say")
    public String sayHello() {
        return person.toString();
    }
}

附上Person类代码:

public class Person {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "name=" + name + " " + "age" + " " + age;
    }
}

输出结果:

name=ty age=26

尽管我们没有显示地配置person bean,但是在spring容器中还是存在它的实例,这就是我们利用自定义注解实现bean的实例化的结果。