您的位置:首页 > 其它

解析字段上的注解并为该字段注入一个对象

2016-05-22 00:54 441 查看
1,创建一个注解类package com.sunyb.annotation;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;/*** 用户实体注解类* @author sunyb* @since 2016-05-21* @version 1.0*///运行时注解@Retention(RetentionPolicy.RUNTIME)public @interface Inject {String name();String password();int age();}2,创建一个User实体类<pre name="code" class="java">package com.sunyb.annotation;/*** 用户实体类* @author sunyb* @since 2016-05-21* @version 1.0*/public class User {private String name;private String password;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", password='" + password + '\'' +", age=" + age +'}';}}
3,创建一个LoginDAOpackage com.sunyb.annotation;/*** 用户登录DAO* @author sunyb* @since  2016-05-21* @version 1.0*/public class LoginDao {@Inject(name="zhangsan", password="123", age=18)private User user;public void login(){System.out.println("Current user:" + user);}}4,创建一个LoginDao工厂类
package com.sunyb.annotation;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
* LoginDao工厂类
* @author sunyb
* @since  2016-05-21
* @version 1.0
*/
public class LoginDaoFactory {
/**
* 创建LoginDao对象
* @return
*/
public static LoginDao createLoginDao(){
// 1,首先创建一个LoginDao对象
LoginDao dao = new LoginDao();

//2,然后反射出LoginDao对象上所有的字段
Field[] fields = dao.getClass().getDeclaredFields();

//3,遍历得到每个Field
if(fields != null){
for(Field field : fields){
//设置暴力访问
field.setAccessible(true);

//获取到该字段上指定的注解:Inject
//@Inject(name="zhangsan", password="123", age=18)
Inject inject = field.getAnnotation(Inject.class);

//如果当前字段上没有Inject注解,则获取到的为null,继续下一次循环
if (inject == null){
continue;
}

//如果程序走到这里,说明已经找到Inject注解
//使用注解上的信息创建一个user对象,并赋值给LoginDao
//为了通用,我们不直接创建user,而是使用反射技术实例化对象
//例如:private User user;
//field.getType()的返回值为Class,可以使用Class实例化具体的对象
try {
Object obj = field.getType().newInstance();

//使用注解的信息,给obj对象赋值
injectToObject(inject, obj);

//使用反射,调用Loginao的set方法,并把obj对象设置进去
field.set(dao, obj);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

return dao;
}

/**
* 使用inject这个注解上的信息,给obj对象赋值
* @param inject  注解
* @param obj  对象
*/
private static void injectToObject(Inject inject, Object obj) {
//1,首先得到inject这个注解上所有的方法
//@Inject(name="zhangsan", password="123", age=18)
Method[] methods = inject.getClass().getMethods();

//循环遍历出每个方法
for(Method method : methods){
//获取到方法名称,例如:name() ,  age()
String methodName = method.getName();

//使用内省技术获取到obj对象上与方法名称相同的属性
try {
PropertyDescriptor pd = new PropertyDescriptor(methodName, obj.getClass());

//如果代码走到这里,说明已经找到了obj中的属性名称和注解上的方法相同
//例如本例中:Inject注解有一个name()方法,而User对象中有一个name属性
//开始使用反射技术调用inject这个注解上的方法,例如调用String name()这个方法
//参数为空所以传null,返回值为String,其实是注解上该方法的返回值
Object value = method.invoke(inject, null);

//把得到的值赋值给具体的对象
//首先通过内省,得到对象的写方法
Method setMethod = pd.getWriteMethod();
//最后,完成setter方法的调用,即完成赋值
setMethod.invoke(obj, value);
} catch (Exception e) {
//如果发生异常,说明该注解上的这个方法,在obj对象中没有与之名称相同的属性,则继续循环
continue;
}

}
}
}
5,测试程序:
<pre name="code" class="java"> LoginDao dao = LoginDaoFactory.createLoginDao();dao.login();
6,运行结果如下:
Current user:User{name='zhangsan', password='123', age=18}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: