我们知道,Spring中大量使用了反射机制,那么究竟是什么地方使用了呢?就从源头说起吧。
一 反射源头Class类
对类的概念我们已经非常熟悉了。比如可以有Student这个类,Person这个类。但是我们要知道,有一个叫Class的类,它是反射的源头。
正常方式:通过完整的类名—>通过new实例化—>取得实例化对象
反射方式:实例化对象—>getClass()方法—>通过完整的类名
一个简单的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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这个类,有三种方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
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这个类实例化类
①无参构造
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
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();
}
}
}
|
②有参构造
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
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实例化
1
2
|
bean.xml
<bean id=
"id"
class
=
"com.xy.Student"
/>
|
Spring将采用的代码创建代码Java实例
1
2
|
Class c = Class.forName(
"com.xy.Student"
);
Object bean = c.newInstance();
|
四 Class类调用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
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注入例子
1
2
3
4
|
bean.xml
<bean id=
"id"
class
=
"com.xy.Student"
>
<property name=
"stuName"
value=
"xy"
/>
</bean>
|
Spring将采用的代码创建代码Java实例,并注入值:
1
2
|
Class c = Class.forName(
"com.xy.Student"
);
Object bean = c.newInstance();
|
通过一些操作获取对stuName对应的setter方法名
1
2
3
|
String setname =
"set"
+
"StuName"
;
Method method = c.getMehod(setname,String.Class);
method.invoke(bean,
"xy"
);
|
这样就完成了最基本的注入操作。当然,Spring还可以通过构造函数进行注入。这样就参考第二点有参构造的Class的使用。
Class还可以访问Annotation,这样就Spring使用注解的时候,可以完成注入的功能。
七 总结
反射的内容还是很多的,需要系统的学习。当然,Spring也是。
本文出自 “IT Fat Man” 博客,请务必保留此出处http://woshixy.blog.51cto.com/5637578/1060263