01、Java反射机制概述
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。
加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射。
1、动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。主要动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang。
2、静态语言
与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++。
- Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。Java的动态性让编程的时候更加灵活!
- Java反射机制提供的功能
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时获取泛型信息
- 在运行时调用任意一个对象的成员变量和方法
- 在运行时处理注解
- 生成动态代理
- 反射相关的主要API
java.lang.Class
:代表一个类java.lang.reflect.Method
:代表类的方法java.lang.reflect.Field
:代表类的成员变量java.lang.reflect.Constructor
:代表类的构造器
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import org.junit.Test;
public class ReflectionTest {
@Test public void test(){
Person p1 = new Person("jay",21);
p1.age = 15; System.out.println(p1.toString());
p1.show();
} }
|
Person类
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
| package github;
public class Person { private String name; public int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public Person() { }
public Person(String name, int age) { this.name = name; this.age = age; }
private Person(String name) { this.name = name; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; }
public void show(){ System.out.println("你好,我是🔔"); }
private String showNation(String nation){ System.out.println("喷子实在太多了!!!" + nation); return nation; } }
|
1.1、使用反射,实现同上的操作
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
| import org.junit.Test;
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
public class ReflectionTest {
@Test public void test2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { Class clazz = Person.class; Constructor cons = clazz.getConstructor(String.class,int.class); Object obj = cons.newInstance("Jon",18); Person p = (Person) obj; System.out.println(p.toString()); Field age = clazz.getDeclaredField("age"); age.set(p,10); System.out.println(p.toString());
Method show = clazz.getDeclaredMethod("show"); show.invoke(p);
} }
|
1.2、反射的强大:调用类的私有结构
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
| import org.junit.Test;
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;
public class ReflectionTest { @Test public void test2() throws Exception{ Class clazz = Person.class; Constructor cons = clazz.getConstructor(String.class,int.class); Object obj = cons.newInstance("Jon",18); Person p = (Person) obj; System.out.println(p.toString()); Field age = clazz.getDeclaredField("age"); age.set(p,10); System.out.println(p.toString());
Method show = clazz.getDeclaredMethod("show"); show.invoke(p);
System.out.println("+++++++++++++++++++++++++");
Constructor cons2 = clazz.getDeclaredConstructor(String.class); cons2.setAccessible(true); Person p1 = (Person) cons2.newInstance("kalo"); System.out.println(p1);
Field name = clazz.getDeclaredField("name"); name.setAccessible(true); name.set(p1,"Taoyao"); System.out.println(p1);
Method showNation = clazz.getDeclaredMethod("LiNin", String.class); showNation.setAccessible(true); String nation = (String) showNation.invoke(p1,"FaceBook"); System.out.println(nation); }
}
|
02、理解Class类并获取Class实例
2.3、Class类的理解
Class类的常用方法
2.4、获取Class实例的4种方式
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
| import org.junit.Test;
import java.lang.annotation.ElementType; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;
public class ReflectionTest {
@Test public void test3() throws ClassNotFoundException { Class c1 = Person.class; System.out.println(c1);
Person p1 = new Person(); Class c2 = p1.getClass(); System.out.println(c2);
Class c3 = Class.forName("www.gh110.com");
System.out.println(c3);
System.out.println(c1 == c2); System.out.println(c1 == c3);
ClassLoader classLoader = ReflectionTest.class.getClassLoader(); Class c4 = classLoader.loadClass("www.gh110.com"); System.out.println(c4);
System.out.println(c1 == c4); } }
|
2.5、Class实例对应的结构的说明
1、哪些类型可以有Class对象?
(1)class
:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类 (2)interface
:接口 (3)[]
:数组 (4)enum
:枚举 (5)annotation
:注解@interface
(6)primitivetype
:基本数据类型 (7)void
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
| import org.junit.Test; import java.lang.annotation.ElementType; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;
public class ReflectionTest {
@Test public void test4() { Class s1 = Object.class; Class s2 = Comparable.class; Class s3 = String[].class; Class s4 = int[][].class; Class s5 = ElementType.class; Class s6 = Override.class; Class s7 = int.class; Class s8 = void.class; Class s9 = Class.class;
int[] a = new int[10]; int[] b = new int[100]; Class s10 = a.getClass(); Class s11 = b.getClass(); System.out.println(s10 == s11); }
}
|
03、类的加载与ClassLoader的理解
3.6、了解:类的加载过程
当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。
说明
- 加载:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口(即引用地址)。所有需要访问和使用类数据只能通过这个Class对象。这个加载的过程需要类加载器参与。
- 链接:将Java类的二进制代码合并到JVM的运行状态之中的过程。
- 验证:确保加载的类信息符合JVM规范,例如:以cafe开头,没有安全方面的问题
- 准备:正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。
- 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。
- 初始化:
- 执行类构造器()方法的过程。类构造器()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。
- 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
- 虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步。
3.7、了解:什么时候会发生类初始化?
- 类的主动引用(一定会发生类的初始化)
- 当虚拟机启动,先初始化main方法所在的类
- new一个类的对象
- 调用类的静态成员(除了final常量)和静态方法
- 使用java.lang.reflect包的方法对类进行反射调用
- 当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类
- 类的被动引用(不会发生类的初始化)
- 当访问一个静态域时,只有真正声明这个域的类才会被初始化
- 通过数组定义类引用,不会触发此类的初始化
- 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)
3.8、ClassLoader的理解
- 类加载器的作用:
- 类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
- 类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象。
- 类加载器作用是用来把类(class)装载进内存的。JVM 规范定义了如下类型的类的加载器。
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
| import org.junit.Test;
public class ClassLoaderTest { @Test public void test1(){ ClassLoader classLoader = ClassLoaderTest.class.getClassLoader(); System.out.println(classLoader); ClassLoader classLoader1 = classLoader.getParent(); System.out.println(classLoader1); ClassLoader classLoader2 = classLoader1.getParent(); System.out.println(classLoader2);
ClassLoader classLoader3 = String.class.getClassLoader(); System.out.println(classLoader3); } }
|
3.9、使用ClassLoader加载配置文件
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
| import org.junit.Test;
import java.io.InputStream; import java.util.Properties;
public class ClassLoaderTest {
@Test public void test2() throws Exception { Properties pros = new Properties();
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader(); InputStream is = classLoader.getResourceAsStream("jdbc1.properties"); pros.load(is);
String user = pros.getProperty("user"); String password = pros.getProperty("password"); System.out.println("user = " + user + ",password = " + password); } }
|
04、通过反射,创建运行时类的对象
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
| import org.junit.Test;
public class NewInstanceTest {
@Test public void test() throws Exception { Class<Person> clazz = Person.class;
Person obj = clazz.newInstance(); System.out.println(obj); } }
|
4.1、举例体会反射的动态性
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
| import org.junit.Test; import java.util.Random;
public class NewInstanceTest {
@Test public void test2(){ for(int i = 0;i < 100;i++){ int num = new Random().nextInt(3); String classPath = ""; switch(num){ case 0: classPath = "java.util.Date"; break; case 1: classPath = "java.lang.Object"; break; case 2: classPath = "www.java.Person"; break; } try { Object obj = getInstance(classPath); System.out.println(obj); } catch (Exception e) { e.printStackTrace(); } } }
public Object getInstance(String classPath) throws Exception { Class clazz = Class.forName(classPath); return clazz.newInstance(); } }
|
05、获取运行时类的完整结构
5.1、提供结构丰富Person类
1、Person类
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
| @MyAnnotation(value="java") public class Person extends Creature<String> implements Comparable<String>,MyInterface{
private String name; int age; public int id;
public Person() { }
@MyAnnotation(value="C++") Person(String name){ this.name = name; }
private Person(String name,int age){ this.name = name; this.age = age; }
@MyAnnotation private String show(String nation){ System.out.println("我来自" + nation + "星系"); return nation; }
@Override public void info() { System.out.println("火星喷子"); }
public String display(String play){ return play; }
@Override public int compareTo(String o) { return 0; } }
|
2、Creature类
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import java.io.Serializable;
public abstract class Creature <T> implements Serializable { private char gender; public double weight;
private void breath(){ System.out.println("太阳系"); }
public void eat(){ System.out.println("银河系"); } }
|
3、MyInterface
1 2 3
| public interface MyInterface { void info(); }
|
4、MyAnnotation
1 2 3 4 5 6 7 8 9 10 11
| import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String value() default "hello world"; }
|
5.2、获取运行时类的属性结构及其内部结构
1、Person类
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
| package github2;
@MyAnnotation(value="java") public class Person extends Creature<String> implements Comparable<String>,MyInterface{
private String name; int age; public int id;
public Person() { }
@MyAnnotation(value="C++") Person(String name){ this.name = name; }
private Person(String name,int age){ this.name = name; this.age = age; }
@MyAnnotation private String show(String nation){ System.out.println("我来自" + nation + "星系"); return nation; }
@Override public void info() { System.out.println("火星喷子"); }
public String display(String play){ return play; }
@Override public int compareTo(String o) { return 0; } }
|
2、测试类
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
| import github2.Person; import org.junit.Test;
import java.lang.reflect.Field; import java.lang.reflect.Modifier;
public class FieldTest {
@Test public void test(){ Class clazz = Person.class; Field[] fields = clazz.getFields(); for(Field f : fields){ System.out.println(f); } System.out.println("++++++++++++++++++"); Field[] declaredFields = clazz.getDeclaredFields(); for(Field f : declaredFields){ System.out.println(f); } }
@Test public void test2(){ Class clazz = Person.class; Field[] declaredFields = clazz.getDeclaredFields(); for(Field f : declaredFields){ int modifier = f.getModifiers(); System.out.print(Modifier.toString(modifier) + "\t"); System.out.println("+++++++++++++++++++++++++++"); Class type = f.getType(); System.out.print(type.getName() + "\t"); System.out.println("***************************"); String fName = f.getName(); System.out.print(fName); } } }
|
5.3、获取运行时类的方法结构
1、Person类
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
| package github2;
@MyAnnotation(value="java") public class Person extends Creature<String> implements Comparable<String>,MyInterface{
private String name; int age; public int id;
public Person() { }
@MyAnnotation(value="C++") Person(String name){ this.name = name; }
private Person(String name,int age){ this.name = name; this.age = age; }
@MyAnnotation private String show(String nation){ System.out.println("我来自" + nation + "星系"); return nation; }
@Override public void info() { System.out.println("火星喷子"); }
public String display(String play){ return play; }
@Override public int compareTo(String o) { return 0; } }
|
2、测试类
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
| package github3;
import github2.Person; import org.junit.Test;
import java.lang.reflect.Method;
public class MythodTest { @Test public void test(){ Class clazz = Person.class; Method[] methods = clazz.getMethods(); for(Method m : methods){ System.out.println(m + "****"); } System.out.println("++++++++++++++++++++++++++++"); Method[] declaredMethods = clazz.getDeclaredMethods(); for(Method m : declaredMethods){ System.out.println(m); } } }
|
5.4、获取运行时类的方法的内部结构
1、Person类
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
| @MyAnnotation(value="java") public class Person extends Creature<String> implements Comparable<String>,MyInterface{
private String name; int age; public int id;
public Person() { }
@MyAnnotation(value="C++") Person(String name){ this.name = name; }
private Person(String name,int age){ this.name = name; this.age = age; }
@MyAnnotation private String show(String nation){ System.out.println("我来自" + nation + "星系"); return nation; }
@Override public void info() { System.out.println("火星喷子"); }
public String display(String interests,int age) throws Exception{ return interests + age; }
@Override public int compareTo(String o) { return 0; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + '}'; } }
|
2、测试类
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
| package github3;
import github2.Person; import org.junit.Test;
import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier;
public class MythodTest {
@Test public void test2() { Class clazz = Person.class; Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method m : declaredMethods) { Annotation[] annos = m.getAnnotations(); for (Annotation a : annos) { System.out.println(a + "KKKK"); }
System.out.print(Modifier.toString(m.getModifiers()) + "\t");
System.out.print(m.getReturnType().getName() + "\t");
System.out.print(m.getName()); System.out.print("("); Class[] pTs = m.getParameterTypes(); if(!(pTs == null && pTs.length == 0)){ for(int i = 0;i < pTs.length;i++){ if(i == pTs.length - 1){ System.out.print(pTs[i].getName() + " args_" + i); break; } System.out.print(pTs[i].getName() + " args_" + i + ","); } } System.out.print(")");
Class[] eTs = m.getExceptionTypes(); if(eTs.length > 0){ System.out.print("throws "); for(int i = 0;i < eTs.length;i++){ if(i == eTs.length - 1){ System.out.print(eTs[i].getName()); break; } System.out.print(eTs[i].getName() + ","); } } System.out.println("TQA"); } }
}
|
5.5、获取运行时类的构造器结构
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
| package github3;
import github2.Person; import org.junit.Test;
import java.lang.reflect.Constructor;
public class OtherTest {
@Test public void test(){ Class clazz = Person.class; Constructor[] constructors = clazz.getConstructors(); for(Constructor c : constructors){ System.out.println(c); } System.out.println("************************"); Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); for(Constructor c : declaredConstructors){ System.out.println(c); } } }
|
5.6、获取运行时类的父类及父类的泛型
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
| package github3;
import github2.Person; import org.junit.Test;
import java.lang.reflect.Constructor; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type;
public class OtherTest {
@Test public void test2(){ Class clazz = Person.class; Class superclass = clazz.getSuperclass(); System.out.println(superclass); }
@Test public void test3(){ Class clazz = Person.class; Type genericSuperclass = clazz.getGenericSuperclass(); System.out.println(genericSuperclass); }
@Test public void test4(){ Class clazz = Person.class; Type genericSuperclass = clazz.getGenericSuperclass(); ParameterizedType paramType = (ParameterizedType) genericSuperclass; Type[] actualTypeArguments = paramType.getActualTypeArguments();
System.out.println(((Class)actualTypeArguments[0]).getName()); } }
|
5.7、获取运行时类的接口、所在包、注解等
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
| package github3;
import github2.Person; import org.junit.Test;
import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type;
public class OtherTest {
@Test public void test5(){ Class clazz = Person.class;
Class[] interfaces = clazz.getInterfaces(); for(Class c : interfaces){ System.out.println(c); } System.out.println("++++++++++++++++++++++"); Class[] interfaces1 = clazz.getSuperclass().getInterfaces(); for(Class c : interfaces1){ System.out.println(c); } }
@Test public void test6(){ Class clazz = Person.class; Package pack = clazz.getPackage(); System.out.println(pack); }
@Test public void test7(){ Class clazz = Person.class; Annotation[] annotations = clazz.getAnnotations(); for(Annotation annos : annotations){ System.out.println(annos); } } }
|
06、调用运行时类的指定结构
6.1、调用运行时类中的指定属性
1、Person类
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
| package github2;
@MyAnnotation(value="java") public class Person extends Creature<String> implements Comparable<String>,MyInterface{
private String name; int age; public int id;
public Person() { }
@MyAnnotation(value="C++") Person(String name){ this.name = name; }
private Person(String name,int age){ this.name = name; this.age = age; }
@MyAnnotation private String show(String nation){ System.out.println("我来自" + nation + "星系"); return nation; }
@Override public void info() { System.out.println("火星喷子"); }
public String display(String interests,int age) throws Exception{ return interests + age; }
@Override public int compareTo(String o) { return 0; }
@Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", id=" + id + '}'; } }
|
2、测试类
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
| package github3;
import github2.Person; import org.junit.Test;
import java.lang.reflect.Field;
public class ReflectionTest {
@Test public void testField() throws Exception { Class clazz = Person.class;
Person p = (Person) clazz.newInstance();
Field id = clazz.getField("id");
id.set(p,1001);
int pId = (int) id.get(p); System.out.println(pId); }
@Test public void testField1() throws Exception { Class clazz = Person.class;
Person p = (Person) clazz.newInstance();
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(p,"Jam"); System.out.println(name.get(p)); } }
|
6.2、调用运行时类中的指定方法
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 github3;
import github2.Person; import org.junit.Test;
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;
public class ReflectionTest {
@Test public void testMethod() throws Exception { Class clazz = Person.class; Person p = (Person) clazz.newInstance();
Method show = clazz.getDeclaredMethod("show", String.class);
show.setAccessible(true);
Object returnValue = show.invoke(p,"CCA"); System.out.println(returnValue);
System.out.println("+++++++++如何调用静态方法+++++++++++");
Method showDesc = clazz.getDeclaredMethod("showDown"); showDesc.setAccessible(true);
Object returnVal = showDesc.invoke(Person.class); System.out.println(returnVal); } }
|
6.3、调用运行时类中的指定构造器
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
| import github2.Person; import org.junit.Test;
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method;
public class ReflectionTest {
@Test public void testConstructor() throws Exception { Class clazz = Person.class;
Constructor constructor = clazz.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
Person per = (Person) constructor.newInstance("Tom"); System.out.println(per); } }
|
07、反射的应用:动态代理
7.1、代理模式与动态代理
代理设计模式的原理:
使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上。
之前为大家讲解过代理机制的操作,属于静态代理,特征是代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理。最好可以通过一个代理类完成全部的代理功能。
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
动态代理使用场合:
动态代理相比于静态代理的优点:
抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,我们可以更加灵活和统一的处理众多的方法。
7.2、静态代理举例
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
|
interface ClothFactory{ void produceCloth(); }
class PersonTest implements ClothFactory{ private ClothFactory factory;
public PersonTest(ClothFactory factory){ this.factory = factory; }
@Override public void produceCloth() { System.out.println("造纸厂开始做一些准备工作");
factory.produceCloth();
System.out.println("造纸厂做一些后续收尾工作"); } }
class NeckTest implements ClothFactory{
@Override public void produceCloth() { System.out.println("造纸厂计划生产一批卫生纸"); } }
public class StaticProxyTest { public static void main(String[] args) { ClothFactory word = new NeckTest();
ClothFactory proxyPaperFactory = new PersonTest(word);
proxyPaperFactory.produceCloth(); } }
|
7.3、动态代理举例
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 83
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
interface Moon{ String getBelief();
void Object(String Moon); }
class Venus implements Moon{
@Override public String getBelief() { return "The only planet in the solar system without a magnetic field."; }
@Override public void Object(String MinMoon) { System.out.println("周围有很多" + MinMoon); } }
class BookTest{
public static Object getProxyInstance(Object obj){ DeskTest hander = new DeskTest(); hander.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),hander); } }
class DeskTest implements InvocationHandler{
private Object obj;
public void bind(Object obj){ this.obj = obj; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object returnValue = method.invoke(obj,args);
return returnValue; } }
public class ProductTest { public static void main(String[] args) { Venus superMan = new Venus(); Moon NumTest = (Moon) BookTest.getProxyInstance(superMan); String belief = NumTest.getBelief(); System.out.println(belief); NumTest.Object("四川大巴山");
System.out.println("+++++++++++++++++++");
NeckTest fox = new NeckTest(); ClothFactory ween = (ClothFactory) BookTest.getProxyInstance(fox);
ween.produceCloth(); } }
|
7.4、AOP与动态代理的举例
前面介绍的Proxy和InvocationHandler,很难看出这种动态代理的优势,下面介绍一种更实用的动态代理机制
- 改进后的说明:代码段1、代码段2、代码段3和深色代码段分离开了,但代码段1、2、3又和一个特定的方法A耦合了!最理想的效果是:代码块1、2、3既可以执行方法A,又无须在程序中以硬编码的方式直接调用深色代码的方法。
- 使用Proxy生成一个动态代理时,往往并不会凭空产生一个动态代理,这样没有太大的意义。通常都是为指定的目标对象生成动态代理
- 这种动态代理在AOP中被称为AOP代理,AOP代理可代替目标对象,AOP代理包含了目标对象的全部方法。但AOP代理中的方法与目标对象的方法存在差异:AOP代理里的方法可以在执行目标方法之前、之后插入一些通用处理。
举例
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
|
interface ClothFactory{ void produceCloth(); }
class PersonTest implements ClothFactory{ private ClothFactory factory;
public PersonTest(ClothFactory factory){ this.factory = factory; }
@Override public void produceCloth() { System.out.println("造纸厂开始做一些准备工作");
factory.produceCloth();
System.out.println("造纸厂做一些后续收尾工作"); } }
class NeckTest implements ClothFactory{
@Override public void produceCloth() { System.out.println("造纸厂计划生产一批卫生纸"); } }
public class StaticProxyTest { public static void main(String[] args) { ClothFactory word = new NeckTest();
ClothFactory proxyPaperFactory = new PersonTest(word);
proxyPaperFactory.produceCloth(); } }
|
测试类
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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| package github4;
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
interface Moon{ String getBelief();
void Object(String Moon); }
class Venus implements Moon{
@Override public String getBelief() { return "The only planet in the solar system without a magnetic field."; }
@Override public void Object(String MinMoon) { System.out.println("周围有很多" + MinMoon); } }
class BookTest{
public static Object getProxyInstance(Object obj){ DeskTest hander = new DeskTest(); hander.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),hander); } }
class DeskTest implements InvocationHandler{
private Object obj;
public void bind(Object obj){ this.obj = obj; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { SunTest util = new SunTest(); util.Star();
Object returnValue = method.invoke(obj,args);
util.Star2();
return returnValue; } }
class SunTest{
public void Star(){ System.out.println("====================通用方法一====================");
}
public void Star2(){ System.out.println("====================通用方法二===================="); }
}
public class ProductTest { public static void main(String[] args) { Venus superMan = new Venus(); Moon NumTest = (Moon) BookTest.getProxyInstance(superMan); String belief = NumTest.getBelief(); System.out.println(belief); NumTest.Object("四川大巴山");
System.out.println("+++++++++++++++++++");
NeckTest fox = new NeckTest(); ClothFactory ween = (ClothFactory) BookTest.getProxyInstance(fox);
ween.produceCloth(); } }
|