读书人

传智播客Spring2.5之施用@Resource注解

发布时间: 2012-08-22 09:50:35 作者: rapoo

传智播客Spring2.5之使用@Resource注解完成属性装配

传智播客Spring2.5之使用@Resource注解完成属性装配?(2009-08-11 09:41:16)传智播客Spring2.5之施用@Resource注解完成属性装配转载标签:?

it分类:?传智视频学习体会

前面我们都是用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一样使用了!!

读书人网 >Web前端

热点推荐