springboot自定义注解(二)

在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的实例化的结果。

猜你喜欢

转载自blog.csdn.net/u012740706/article/details/82191631