Spring中的反射機制淺析
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
1 反射的源頭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
2 利用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();
}
}
}
3 Spring中使用Class例項化
bean.xml
<bean id="id" class="com.xy.Student" />
Spring將採用的程式碼建立程式碼Java例項
Class c = Class.forName("com.xy.Student");
Object bean = c.newInstance();
4 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();
}
}
}
5 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;
}
}
6 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使用註解時可完成注入的功能。
7 總結
反射的內容還是很多的,需要系統的學習。當然Spring也是。
感覺有幫助請您賞一杯茶錢,金額隨意。您的鼓勵是我寫作的動力。
我的新微信公眾號【IT徐胖子】,請您關注!