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;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
", age=" + age +
'}';
}
}
3,创建一个LoginDAO
package 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);
}
}
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}