我們知道,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這個類,有三種方法:
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());
二 利用class這個類執行個體化類
①無參構造
public class person {
private string name;
private int age;
.............省略getter,setter..............
@override
public string tostring()
return "person [name=" + name + ", age=" + age + "]";
}
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();
}
}
②有參構造
public class person
public person(stringname,int age){
this.name = name;
this.age = age;
.............省略getter,setter..............
import java.lang.reflect.constructor;
// 如果沒有一個空構造方法
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類調用方法
public void add()
system.out.println("add");
public void addwithparameters(string name, int age)
system.out.println("add帶參數方法" + name + age);
import java.lang.reflect.method;
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方法。
省略getter,setter
}
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);
}
e.printstacktrace();
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 id="id" class="com.xy.student">
<property name="stuname" value="xy" />
</bean>
spring将采用的代碼建立代碼java執行個體,并注入值:
通過一些操作擷取對stuname對應的setter方法名
string setname = "set" + "stuname";
method method = c.getmehod(setname,string.class);
method.invoke(bean,"xy");
這樣就完成了最基本的注入操作。當然,spring還可以通過構造函數進行注入。這樣就參考第二點有參構造的class的使用。
class還可以通路annotation,這樣就spring使用注解的時候,可以完成注入的功能。
七 總結
反射的内容還是很多的,需要系統的學習。當然,spring也是。