Spring原理学习--实现一个类似@Autowired的注解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wzl19870309/article/details/84957543

本次记录和大家分享的是对注解原理的一些认识,我这里主要通过实现Spring的后置处理器BeanPostProcessor来进行赋值处理

首先定一个我的注解:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface MyAnnotation {

    String value() default "";
}

然后Processor,来实现接口BeanPostProcessor

@Component
public class ServiceInjectProcessor implements BeanPostProcessor {

    @Autowired
    private ApplicationContext applicationContext;

    //bean初始化之前要调用的方法,这里直接返回
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    //bean初始化之后要调用的方法,这里判断如果有自定义注解@MyAnnotation时,做进一步处理
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        Class<?> targeClass = bean.getClass();
        Field[] fields = targeClass.getDeclaredFields();
        for (Field field: fields ) {
            if (field.isAnnotationPresent(MyAnnotation.class)) {  //判断属性是否是自定义注解@MyAnnotation
                if(!field.getType().isInterface()) {  //加自定义注解的属性必须是接口类型(这样才可能出现多个不同的实例bean)
                    throw new BeanCreationException("MyAnnotation field must be declared an interface");
                } else {
                    try {
                        //为属性赋值
                        this.hanldMyAnnotation(field, bean, field.getType());
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return bean;
    }

    private void hanldMyAnnotation(Field field, Object bean, Class type) throws IllegalAccessException {
        //获取所有该属性接口的实例bean
        Map<String,Object> beans = this.applicationContext.getBeansOfType(type);
        //设置该域可设置修改
        field.setAccessible(true);
        //获取注解@MyAnnotation中配置的value值
        String injectVal = field.getAnnotation(MyAnnotation.class).value();
        //将找到的实例赋值给属性域
        field.set(bean,beans.get(injectVal));
    }
}

定义服务接口LuxyService

public interface LuxyService {

    public void sayHello(String name);
}

写两个service,分别实现接口LuxyService

@Service("luxyService_1")
public class LuxyServiceImpl implements LuxyService {

    @Override
    public void sayHello(String name) {
           System.out.println("I am luxyService_1 " + name);
    }

}
@Service("luxyService_2")
public class LuxyServiceImpl2 implements LuxyService {

    @Override
    public void sayHello(String name) {
        System.out.println("I am luxyService_2 " + name);
    }
}

写另一个服务类,在其中增加LuxyService属性,并在属性上增加自定义注解

@Service
public class TestService {

    //增加注解(@MyAnnotation),并设置value为luxyService_2
    @MyAnnotation("luxyService_2")
    private LuxyService luxyService;

    public void sayHello() {
        System.out.println(luxyService);
        luxyService.sayHello("hello MyAnnotation");
    }

}

测试类

public class LuxyCongfigTest {

    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LuxyMainConfig.class); //加入配置类,加载IOC容器

    @Test
    public void testConfig(){
        TestService testService = (TestService)context.getBean(TestService.class);
        testService.sayHello();
    }
}

测试结果如下:

I am luxyService_2 hello MyAnnotation

顺利搞定。当然这里只是简单做了注解加在属性上的实现,如果大家对其他位置感兴趣,可以自己尝试尝试

分享仅供交流学习,不足之处还请多多执教

猜你喜欢

转载自blog.csdn.net/wzl19870309/article/details/84957543
今日推荐