我們知道,Spring中大量使用了反射機制,那么究竟是什么地方使用了呢?就從源頭說起吧。
?
一? 反射源頭Class類
對類的概念我們已經非常熟悉了。比如可以有Student這個類,Person這個類。但是我們要知道,有一個叫Class的類,它是反射的源頭。
?
正常方式:通過完整的類名—>通過new實例化—>取得實例化對象
反射方式:實例化對象—>getClass()方法—>通過完整的類名
?
一個簡單的例子:
package cn.classes;
public class OneClass {
}
package cn.test;
import cn.classes.OneClass;
public class Test {
??? public static void main(String[] args) {
??????? OneClass c = new OneClass();
????????System.out.println(c.getClass().getName());
?? }
}
輸出結果:cn.classes.OneClass
我們需要使用反射,就要獲得Class這個類,有三種方法:
package cn.classes;
public class OneClass {
}
import cn.classes.OneClass;
public class Test {
public static void main(String[] args) {
???? Class<?> c1 = null;
???? Class<?> c2 = null;
???? Class<?> c3 = null;
???? try?
??? {
???????? // 方法一:forName(重要)
?????????c1 = Class.forName("cn.classes.OneClass");
?? ?}?
??? catch (ClassNotFoundException e)?
??? {
???????? e.printStackTrace();
????}
???? // 方法二
?????c2 = new OneClass().getClass();
??
???? // 方法三
?????c3 = OneClass.class;
???? System.out.println(c1.getName());
???? System.out.println(c2.getName());
???? System.out.println(c3.getName());
?? }
}
輸出結果:cn.classes.OneClass
?
?
二 利用Class這個類實例化類
①無參構造
package cn.classes;
public class Person {
??? private String name;
??? private int age;
???? .............省略getter,setter..............
??? @Override
??? public String toString()
??? {
????????? return "Person [name=" + name + ", age=" + age + "]";
??? }
}
package cn.test;
import cn.classes.Person;
public class Test
{
??? // 這樣做必須在類中有一個空構造方法
??? public static void main(String[] args)
??? {
????????????? Class<?> c = null;
?????????????? try
?????????????? {
??????????????????????c = Class.forName("cn.classes.Person");
??????????????????????Person p = (Person)c.newInstance();
????????????????????? p.setName("xy");
????????????????????? p.setAge(20);
????????????????????? System.out.println(p);
?????????????? }?
????????????? catch (Exception e)
????????????? {
????????????????????? e.printStackTrace();
????????????? ?}??
???? }
}
?
②有參構造
package cn.classes;
public class Person
{
??? private String name;
??? private int age;
?????public Person(Stringname,int age){
???????????????? this.name = name;
???????????????? this.age = age;
????}
??? .............省略getter,setter..............????
??? @Override
??? public String toString()
??? {
????????? return "Person [name=" + name + ", age=" + age + "]";
??? }
}
package cn.test;
import java.lang.reflect.Constructor;
import cn.classes.Person;
public class Test
{
??? // 如果沒有一個空構造方法
??? public static void main(String[] args)
??? {
????????? Class<?> c = null;
????????? try
??????????{
??????????????????c = Class.forName("cn.classes.Person");
??????????????????Constructor<?> con = c.getConstructors(String.class,int.class);
??????????????????Person p = (Person)con.newInstance("xy",20);
????????????????? System.out.println(p);
????????? }?
???????? catch (Exception e)
???????? {
??????????????? e.printStackTrace();
???????? }??
??? }
}
?
三 Spring中使用Class實例化
bean.xml
<bean id="id" class="com.xy.Student" />
?
Spring將采用的代碼創建代碼Java實例
Class c = Class.forName("com.xy.Student");
Object bean = c.newInstance();
?
?
四 Class類調用方法
package cn.classes;
public class Person
{
??? public void add()
??? {
?????????? System.out.println("add");
??? }
??? public void addWithParameters(String name, int age)
??? {
??????????? System.out.println("add帶參數方法" + name + age);
??? }
}
package cn.test;
import java.lang.reflect.Method;
public class Test
{
??? public static void main(String[] args)
??? {
???????????? Class<?> c1 = null;
?????????????try
???????????? {
?????????????????? c1 = Class.forName("cn.classes.Person");
?????????????????? // 不帶參數的方法調用
???????????????????Method m = c1.getMethod("add");
???????????????????m.invoke(c1.newInstance());
?
?????????????????? // 帶參數方法調用
???????????????????Method m1 = c1.getMethod("addWithParameters", String.class,?int.class);
???????????????????m1.invoke(c1.newInstance(), "xy", 22);
?????????? ?}
??????????? catch (Exception e)
??????????? {
?????????????????? e.printStackTrace();
??????????? }
??? }
}
?
?
五 Class獲得getter,setter方法
Class這個類可以獲得類的很多信息,比如獲得該類的接口,構造函數,屬性,方法等。我們來看如何獲得getter,setter方法。
package cn.classes;
public class Person
{
??? private String name;
??? private int age;
??? 省略getter,setter??
?}
?
package cn.test;
import java.lang.reflect.Method;
public class Test
{
??? public static void main(String[] args)
??? {
?????????? Class<?> c1 = null;
?????????? Object obj = null;
?????????? try
?????????? {
???????????????????? c1 = Class.forName("cn.classes.Person");
???? ??????????????? obj = c1.newInstance();
???????????????????? setter(obj, "name", "xy", String.class);
???? ??????????????? setter(obj, "age", 20, int.class);
???????????????????? getter(obj, "name");
???????????????????? getter(obj, "age");
?????????? }
?????????? catch (Exception e)
??????????? {
???? ?????????????? e.printStackTrace();
??????????? }
?? }
?? /**
??? * @param obj:要操作的對象
??? * @param att:要操作的屬性
??? * @param value:要設置的屬性內容
??? * @param type:要設置的屬性類型
??? */
??? public static void setter(Object obj, String att, Object value, Class<?> type)
??? {
???????? try
? ?????? {
??????????? // 得到setter方法
???? ???? Method m = obj.getClass().getMethod("set" + initStr(att), type);
???? ???? m.invoke(obj, value);
???????? }
???????? catch (Exception e)
???????? {
???? ???? e.printStackTrace();
???????? }
?? }
?? /**
??? * @param obj:要操作的對象
??? * @param att:要操作的屬性
??? */
?? public static void getter(Object obj, String att)
?? {
??????? try
??????? {
?????????????? // 得到getter方法
???? ????????? Method m = obj.getClass().getMethod("get" + initStr(att));
???? ????????? System.out.println(m.invoke(obj));
?????? ?}
?????? catch (Exception e)
?????? {
???? ????????? e.printStackTrace();
?????? }
?? }
?? public static String initStr(String oldStr)
?? {
???????? String newStr = oldStr.substring(0, 1).toUpperCase() + oldStr.substring(1);
???????? return newStr;
?? }
}
?
六 Spring調用getter,setter方法
我們以setter注入例子
bean.xml
<bean id="id" class="com.xy.Student">
????<property name="stuName" value="xy" />
</bean>
Spring將采用的代碼創建代碼Java實例,并注入值:
Class c = Class.forName("com.xy.Student");
Object bean = c.newInstance();
通過一些操作獲取對stuName對應的setter方法名
String setname = "set" + "StuName";
Method method = c.getMehod(setname,String.Class);
method.invoke(bean,"xy");
這樣就完成了最基本的注入操作。當然,Spring還可以通過構造函數進行注入。這樣就參考第二點有參構造的Class的使用。
Class還可以訪問Annotation,這樣就Spring使用注解的時候,可以完成注入的功能。
?
七 總結
反射的內容還是很多的,需要系統的學習。當然,Spring也是。
本文轉自IT徐胖子的專欄博客51CTO博客,原文鏈接http://blog.51cto.com/woshixy/1060263如需轉載請自行聯系原作者
woshixuye111