传智播客Spring2.5之施用@Resource注解完成属性装配
前面我们都是用XML配制的方式进行依赖对象的注入的,但是这样都在XML配制就会造成一个BEAN下面可能会有很多的property配置,这样就会使得配置文件变得很臃肿,用Spring2.5的注解方式就能够解决这样的问题,在java代码中使用@Resource注解方式进行装配时,我们首先需要在XML配置文件中配置以下信息: <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/> </beans> 这样我们就开启了spring对注解的支持,这种配置隐式注册了多个注释进行解析处理的处理器:AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor, PersistenceAnnotationBeanPostProcessor, RequiredAnnotationBeanPostProcessor,(注:如果我们想要用这个注解,需要加入Spring安装目录的lib\j2ee\common-annotations.jar文件)。 @Resource这个注解可以标在字段上和属性的setter方法上,但它默认是按名称装配,名称可以通过@Resource的name属性指定,如果没有指定name属性,当注解标在字段上,则默认取字段的名称作为bean名寻找依赖对象,当注解标注在属性的setter方法上,既默认取属性名作为bean名称寻找依赖对象 public class PersonServiceBean implements PersonService { @Resource(name=”personDao”) private PersonDao personDao; } (注:如果没有指定name属性,并且按照默认的名称仍然找不到依赖对象时,@Resource注解会回退到按类型匹配,但一旦指定了name属性,就只能按名称装配了) 到底Spring是如何实现注解装配的呢??咱们还是通过自己编写来实现这样的功能,这样就能很清楚的知道它的底层原理了: 首先我们建立一个自己的Annotation来实现自己的自动装配 //注解信息保留在运行期中,也就是这个注解会出现在源代码、运行期和编译后的档中 @Retention(RetentionPolicy.RUNTIME) //这个注解只能出现在字段上和方法上 @Target({ElementType.FIELD, ElementType.METHOD}) public @interface ItcastResource { String name() default ""; } 接着我们在构造方法中添加一个处理Annotation的方法,里面的代码如下: //这里处理注解注入 private void annotationInject() { for(String beanName : sigletons.keySet()) { Object bean = sigletons.get(beanName); if(bean != null) { try { //得到bean里面所定义的所有属性描述信息(判断注解在字段setter的情况) PropertyDescriptor[] ps = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); for(PropertyDescriptor properdesc : ps) { Method setter = properdesc.getWriteMethod();//获取属性的setter方法 //在属性的setter方法上存在ItcastResource注解 if(setter != null && setter.isAnnotationPresent(ItcastResource.class)) { ItcastResource resource = setter.getAnnotation(ItcastResource.class); Object value = null; //注解上指定了name属性 if(resource.name() != null && !"".equals(resource.name())) { value = sigletons.get(resource.name()); } else { //注解上没有指定了name属性 value = sigletons.get(properdesc.getName()); if(value == null) { //通过属性的名称没有找到指定的对象,接着按该字段的类型进行寻找 for(String key : sigletons.keySet()) { //根椐字段类型到所有的BEAN中查找是否有匹配的类型 if(properdesc.getPropertyType().isAssignableFrom(sigletons.get(key).getClass())) { value = sigletons.get(key); break; } } } } setter.setAccessible(true);//允许访问私有的setter方法 setter.invoke(bean, value);//把引用对象注入到属性中 } } //(判断注解在字段的情况) Field[] fields = bean.getClass().getDeclaredFields();//要找私有的字段只能调此方法,如果调用getFileds()就只能找到那些公共的字段 for(Field field : fields) { if(field.isAnnotationPresent(ItcastResource.class)) { //字段上存在注解 ItcastResource resource = field.getAnnotation(ItcastResource.class); Object value = null; //注解上指定了name属性 if(resource.name() != null && !"".equals(resource.name())) { value = sigletons.get(resource.name()); } else { //注解上没有指定了name属性 value = sigletons.get(field.getName()); if(value == null) { //通过属性的名称没有找到指定的对象,接着按该字段的类型进行寻找 for(String key : sigletons.keySet()) { //根椐字段类型到所有的BEAN中查找是否有匹配的类型 if(field.getType().isAssignableFrom(sigletons.get(key).getClass())) { value = sigletons.get(key); break; } } } } field.setAccessible(true);//允许访问private字段 field.set(bean, value);//访问字段的setter方法进行注入 } } } catch (Exception e) { e.printStackTrace(); } } } } 这样我们通过自己编写代码来解析这些注解,最后咱们就可用自己建的这个@ItcastResource注解来跟Spring官方实现的@Resource一样使用了!!传智播客Spring2.5之使用@Resource注解完成属性装配
(2009-08-11 09:41:16)
标签:
it
分类: 传智视频学习体会