版权声明:本文为博主原创文章,未经博主允许不得转载。 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
顺利搞定。当然这里只是简单做了注解加在属性上的实现,如果大家对其他位置感兴趣,可以自己尝试尝试
分享仅供交流学习,不足之处还请多多执教