spring中注解的实现原理

下面的示例来简单的讲述spring注解原理:

本例实现了在set方法上和在字段属性上注解的处理解析。

1、定义注解


Java代码 复制代码 收藏代码
1.package com.yt.annotation; 
2. 
3.import java.lang.annotation.ElementType; 
4.import java.lang.annotation.Retention; 
5.import java.lang.annotation.RetentionPolicy; 
6.import java.lang.annotation.Target; 
7. 
8./**
9. * @Description:定义注解
10. * @ClassName: ZxfResource
11. * @Project: spring-aop
12. * @Author: zxf
13. * @Date: 2011-6-7
14. */ 
15.// 在运行时执行 
16.@Retention(RetentionPolicy.RUNTIME
17.// 注解适用地方(字段和方法) 
18.@Target({ ElementType.FIELD, ElementType.METHOD }) 
19.public @interface ZxfResource { 
20. 
21.    //注解的name属性 
22.    public String name() default ""; 
23.} 


 2、带有注解的服务类


Java代码 复制代码 收藏代码
1.package com.yt.annotation; 
2. 
3./**
4. * @Description: 带有注解的服务
5. * @ClassName: UserDaoImpl
6. * @Project: spring-aop
7. * @Author: zxf
8. * @Date: 2011-6-7
9. */ 
10.public class UserServiceImpl { 
11. 
12.    public UserDaoImpl userDao; 
13.    public User1DaoImpl user1Dao; 
14. 
15.    // 字段上的注解,可以配置name属性 
16.    @ZxfResource 
17.    public User2DaoImpl user2Dao; 
18. 
19.    // set方法上的注解,带有name属性 
20.    @ZxfResource(name = "userDao") 
21.    public void setUserDao(UserDaoImpl userDao) { 
22.        this.userDao = userDao; 
23.    } 
24. 
25.    // set方法上的注解,没有配置name属性 
26.    @ZxfResource 
27.    public void setUser1Dao(User1DaoImpl user1Dao) { 
28.        this.user1Dao = user1Dao; 
29.    } 
30. 
31.    public void show() { 
32.        userDao.show(); 
33.        user1Dao.show1(); 
34.        user2Dao.show2(); 
35.        System.out.println("这里是Service方法........"); 
36.    } 
37.} 


 3、要注入的DAO


Java代码 复制代码 收藏代码
1.package com.yt.annotation; 
2. 
3./**
4. * @Description: 要注入的DAo类
5. * @ClassName: UserDaoImpl
6. * @Project: spring-aop
7. * @Author: zxf
8. * @Date: 2011-6-7
9. */ 
10.public class UserDaoImpl { 
11.     
12.    String name ; 
13.     
14.    public void show(){ 
15.        System.out.println("这里是dao方法........"); 
16.    } 
17.} 



Xml代码 复制代码 收藏代码
1.<?xml version="1.0" encoding="UTF-8"?> 
2.<beans> 
3.    <bean id = "userDao" class="com.yt.annotation.UserDaoImpl" /> 
4.    <bean id = "user1Dao" class="com.yt.annotation.User1DaoImpl" /> 
5.    <bean id = "user2Dao" class="com.yt.annotation.User2DaoImpl" /> 
6.    <bean id = "userService" class = "com.yt.annotation.UserServiceImpl" /> 
7.</beans> 

 
 4、注解处理器


Java代码 复制代码 收藏代码
1.package com.yt.annotation; 
2. 
3.import java.beans.Introspector; 
4.import java.beans.PropertyDescriptor; 
5.import java.lang.reflect.Field; 
6.import java.lang.reflect.Method; 
7.import java.util.ArrayList; 
8.import java.util.HashMap; 
9.import java.util.Iterator; 
10.import java.util.List; 
11.import java.util.Map; 
12.import org.apache.log4j.Logger; 
13.import org.dom4j.Document; 
14.import org.dom4j.DocumentException; 
15.import org.dom4j.Element; 
16.import org.dom4j.io.SAXReader; 
17. 
18./**
19. * @Description: spring中的注解原理
20. * @ClassName: ClassPathXMLApplicationContext
21. * @Project: spring-aop
22. * @Author: zxf
23. * @Date: 2011-6-3
24. */ 
25.public class ClassPathXMLApplicationContext { 
26. 
27.    Logger log = Logger.getLogger(ClassPathXMLApplicationContext.class); 
28. 
29.    List<BeanDefine> beanList = new ArrayList<BeanDefine>(); 
30.    Map<String, Object> sigletions = new HashMap<String, Object>(); 
31. 
32.    public ClassPathXMLApplicationContext(String fileName) { 
33.        //读取配置文件中管理的bean 
34.        this.readXML(fileName); 
35.        //实例化bean 
36.        this.instancesBean(); 
37.        //注解处理器 
38.        this.annotationInject(); 
39.    } 
40. 
41.    /**
42.     * 读取Bean配置文件
43.     * @param fileName
44.     * @return
45.     */ 
46.    @SuppressWarnings("unchecked") 
47.    public void readXML(String fileName) { 
48.        Document document = null; 
49.        SAXReader saxReader = new SAXReader(); 
50.        try { 
51.            ClassLoader classLoader =  
52.                Thread.currentThread().getContextClassLoader(); 
53.            document = saxReader.read(classLoader.getResourceAsStream(fileName)); 
54.            Element beans = document.getRootElement(); 
55.            for (Iterator<Element> beansList = beans.elementIterator();  
56.                beansList.hasNext();) { 
57.                Element element = beansList.next(); 
58.                BeanDefine bean = new BeanDefine( 
59.                        element.attributeValue("id"), 
60.                        element.attributeValue("class")); 
61.                beanList.add(bean); 
62.            } 
63.        } catch (DocumentException e) { 
64.            log.info("读取配置文件出错...."); 
65.        } 
66.    } 
67.     
68.    /**
69.     * 实例化Bean
70.     */ 
71.    public void instancesBean() { 
72.        for (BeanDefine bean : beanList) { 
73.            try { 
74.                sigletions.put(bean.getId(),  
75.                        Class.forName(bean.getClassName()).newInstance()); 
76.            } catch (Exception e) { 
77.                log.info("实例化Bean出错..."); 
78.            } 
79.        } 
80.    } 
81.     
82.    /**
83.     * 注解处理器
84.     * 如果注解ZxfResource配置了name属性,则根据name所指定的名称获取要注入的实例引用,
85.     * 如果注解ZxfResource;没有配置name属性,则根据属性所属类型来扫描配置文件获取要
86.     * 注入的实例引用
87.     * 
88.     */ 
89.    public void annotationInject(){ 
90.        for(String beanName:sigletions.keySet()){ 
91.            Object bean = sigletions.get(beanName); 
92.            if(bean!=null){ 
93.                this.propertyAnnotation(bean); 
94.                this.fieldAnnotation(bean); 
95.            } 
96.        } 
97.    } 
98.     
99.    /**
100.     * 处理在set方法加入的注解
101.     * @param bean 处理的bean
102.     */ 
103.    public void propertyAnnotation(Object bean){ 
104.        try { 
105.            //获取其属性的描述 
106.            PropertyDescriptor[] ps =  
107.                Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); 
108.            for(PropertyDescriptor proderdesc : ps){ 
109.                //获取所有set方法 
110.                Method setter = proderdesc.getWriteMethod(); 
111.                //判断set方法是否定义了注解 
112.                if(setter!=null && setter.isAnnotationPresent(ZxfResource.class)){ 
113.                    //获取当前注解,并判断name属性是否为空 
114.                    ZxfResource resource = setter.getAnnotation(ZxfResource.class); 
115.                    String name =""; 
116.                    Object value = null; 
117.                    if(resource.name()!=null&&!"".equals(resource.name())){ 
118.                        //获取注解的name属性的内容 
119.                        name = resource.name(); 
120.                        value = sigletions.get(name); 
121.                    }else{ //如果当前注解没有指定name属性,则根据类型进行匹配 
122.                        for(String key : sigletions.keySet()){ 
123.                            //判断当前属性所属的类型是否在配置文件中存在 
124.                            if(proderdesc.getPropertyType().isAssignableFrom(sigletions.get(key).getClass())){ 
125.                                //获取类型匹配的实例对象 
126.                                value = sigletions.get(key); 
127.                                break; 
128.                            } 
129.                        } 
130.                    } 
131.                    //允许访问private方法 
132.                    setter.setAccessible(true); 
133.                    //把引用对象注入属性 
134.                    setter.invoke(bean, value);  
135.                } 
136.            } 
137.        } catch (Exception e) { 
138.            log.info("set方法注解解析异常.........."); 
139.        } 
140.    } 
141.     
142.    /**
143.     * 处理在字段上的注解
144.     * @param bean 处理的bean
145.     */ 
146.    public void fieldAnnotation(Object bean){ 
147.        try { 
148.            //获取其全部的字段描述 
149.            Field[] fields = bean.getClass().getFields(); 
150.            for(Field f : fields){ 
151.                if(f!=null && f.isAnnotationPresent(ZxfResource.class)){ 
152.                    ZxfResource resource = f.getAnnotation(ZxfResource.class); 
153.                    String name =""; 
154.                    Object value = null; 
155.                    if(resource.name()!=null&&!"".equals(resource.name())){ 
156.                        name = resource.name(); 
157.                        value = sigletions.get(name); 
158.                    }else{ 
159.                        for(String key : sigletions.keySet()){ 
160.                            //判断当前属性所属的类型是否在配置文件中存在 
161.                            if(f.getType().isAssignableFrom(sigletions.get(key).getClass())){ 
162.                                //获取类型匹配的实例对象 
163.                                value = sigletions.get(key); 
164.                                break; 
165.                            } 
166.                        } 
167.                    } 
168.                    //允许访问private字段 
169.                    f.setAccessible(true); 
170.                    //把引用对象注入属性 
171.                    f.set(bean, value); 
172.                } 
173.            } 
174.        } catch (Exception e) { 
175.            log.info("字段注解解析异常.........."); 
176.        } 
177.    } 
178.     
179.    /**
180.     * 获取Map中的对应的bean实例
181.     * @param beanId
182.     * @return
183.     */ 
184.    public Object getBean(String beanId) { 
185.        return sigletions.get(beanId); 
186.    } 
187. 
188. 
189.    public static void main(String[] args) { 
190.        ClassPathXMLApplicationContext path = new ClassPathXMLApplicationContext( 
191.                "configAnnotation.xml"); 
192.        UserServiceImpl userService =(UserServiceImpl)path.getBean("userService"); 
193.        userService.show(); 
194.    } 
195.} 



@Autowired和@Resource的区别:

 

在Java中使用@Autowired和@Resource注解进行装配,这两个注解分别是:
1、@Autowired按照默认类型(类名称)装配依赖对象,默认情况下它要求依赖对象必须存在,如果允许为null,可以设置它的required属性为false
如果我们按名称装配,可以结合@Qualifie注解一起使用。
 如:
@Autowired @qualifie("personDaoBean")
 private PersonDaoBean personDaoBean;

 @Resource默认按照名称(name="test")进行装配,名称可以通过@resource的name属性设定,当找不到与名称匹配的bean才会按类型装配

 注意:如果没有指定name属性,并且安装默认的名称依然找不到依赖对象时,@Resource会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值