long blogs

进一步有进一步惊喜


  • Home
  • Archive
  • Tags
  •  

© 2025 long

Theme Typography by Makito

Proudly published with Hexo

java反射和动态代理

Posted at 2019-08-05 笔记 java 

Java反射机制

java的反射机制是一种逆向的思维。通常来所,知道一个类,然后new一个对象。而反射便是从一个对象开始,然后反推出它所在的类。前者是抽象到具体的过程。后者是从具体到抽象的过程。
1、类对象Class

  • 通过类的实例获得该类的类对象。使用instance#getClass()方法。即通过具体获得类的框架。
1
2
Peson p = new Person("xiaoming");
Class pClass = p.getClass();

通过pClass可以获得Person类中的接口和函数等方法。当获得class类之后和实例的关系就分开了。

  • 使用Class#getDeclaredField(“name”)->Field来获得类响应的属性。可以是公有的,也可以是私有的。但是获得的只是一个类的模板,想要获得一个实例的具体属性,就要用模板来加载实例,然后返回实例的值。也可以通过该Field来设置相应的值。
    (1)Field#get(instance) 获得instance中对应Field字段的值
    (2)Field#set(instance,value) 设置instance中对应Field字段的值
1
2
3
4
5
6
7
8
9
10
11
// 获得Field对象,是一个模板,该模板是属性name的模板
Field f = pClass.getDeclaredField("name");
// 设置可访问私有属性
f.setAccessible(true);
// 调用Field的get方法来加载p,即获得p中的name属性值
// 等价于p.get("name");
Object value = f.get(p);
System.out.println(value);
// f.set(p,"张三") 对实例p的name属性进行赋值
f.set(p,"张三");
System.out.println(p.getName());

输出结果:

1
2
xiaoming
张三

2、反射调用函数

  • 每个Class类中都含有getMethod的方法。根据该方法返回一个Method的对象。该Mehtod对象便是方法的一个模板,使用Method#invoke(Object obj,Object.. args)来对obj对象执行Method方法。并且传入想要的参数。或者参数类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
String s = "Hello World";
try{
// Method 的方法是String类中substring(beginIndex)中的方法
Method m = String.class.getMethod("substring",int.class);
// invoke 调用,等价于s.substring(6)
String sub = (String) m.invoke(s, 6);
System.out.println(sub);
String sub2 = s.substring(6);
System.out.println(sub2);

Method parseInt = Integer.class.getMethod("parseInt", String.class);
// invoke
Integer n = (Integer) parseInt.invoke(null, "12346");
System.out.println("n=" + n);
}catch(Exception e){
e.printStackTrace();
}

输出结果

1
2
3
World
World
n=12346

动态代理模式

  • 核心函数
    Proxy.newProxyInstance(ClassLoader,Interface,handler)
    第一个参数:ClassLoader。除了jdk自带的一些类:ClassLoader不用使用之外,随意使用classLoader便可以了。
    第二个参数:Interface。需要代理的类的接口,这个决定了所代理的类,以下的参数均通过测试
    1、Student.class.getInterfaces()
    2、new Class[]{Person.class}
    3、student.getClass.getInterfaces()
    第三个参数:handler,实现了Invocation的接口,并且实现 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable函数。method.invoke(object,args)必须object必须匹配接口
  • 简单实现
    接口类:Bird
1
2
3
4
5
6
public interface Bird {
/**
* 鸟
*/
void fly();
}

实现类:Swallow

1
2
3
4
5
public class Swallow implements Bird {
public void fly(){
System.out.println("I'am fly...........");
}
}

接口类:Person

1
2
3
4
public interface Person {
void run();
void say(String str);
}

实现类:Student

1
2
3
4
5
6
7
8
9
public class Student implements Person{
public void run() {
System.out.println("I'am Student running");
}

public void say(String str) {
System.out.println("I'am say "+str);
}
}

MyHandler实现InvocationHandler的接口

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
public class MyHandler implements InvocationHandler{

/**
* 维护的的对象
*/
private Object target;

public MyHandler(){}
/**
* 构造函数,输入要代理的对象
* @param target
*/
public MyHandler(Object target){
this.target = target;
}

/**
* 设置代理对象
* @param target 代理的对象
*/
public void setTarget(Object target) {
this.target = target;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
//代理对象前的操作
System.out.println("before invoke .....");
System.out.println("Method:"+method);

// 调用原有的函数
method.invoke(target, args);

// 调用原有的函数之后
System.out.println("after invoke .....");

return null;
}
}

主类,测试

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
public class Client{
public static void main(String[] args){
Bird realSubject = new Swallow();

try{
// 声明的代理类的处理者
InvocationHandler handler = new MyHandler(realSubject);

// 获得代理类
Bird birdProxy = (Bird)Proxy.newProxyInstance(
handler.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
handler);

System.out.println(birdProxy.getClass().getName());
// 调用鸟飞函数
birdProxy.fly();

Person student = new Student();
((MyHandler) handler).setTarget(student);

// 获得student的代理对象
HelloWorld helloWorld = new HelloWorld();

Person studentProxy =(Person) Proxy.newProxyInstance(
HelloWorld.class.getClassLoader(),
student.getClass().getInterfaces(),
handler);
// 代理类调用函数
studentProxy.run();
studentProxy.say("proxy");

}catch(Exception e){
e.printStackTrace();
}
}
}

输出结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
com.sun.proxy.$Proxy0
before invoke .....
Method:public abstract void com.longquanxiao.proxy.Bird.fly()
I'am fly...........
after invoke .....
before invoke .....
Method:public abstract void com.longquanxiao.proxy.Person.run()
I'am Student running
after invoke .....
before invoke .....
Method:public abstract void com.longquanxiao.proxy.Person.say(java.lang.String)
I'am say proxy
after invoke .....

Share 

 Previous post: java实例化几种方式 Next post: 单元测试unit 

© 2025 long

Theme Typography by Makito

Proudly published with Hexo