目录
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API获取任何类的内部信息,并能直接操作任意对象的内部属性及方法
加载完类以后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,我们形象的称之为:反射
正常方式:引入需要的“包类”名称->通过new实例化->取得实例化对象
反射方式:实例化对象->getClass()方法->得到完整的“包类”名称
补充:
1.动态语言
是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件
改变自身结构
2.静态语言
是与动态语言相对应的,运行时结构不可变的语言就是静态语言
例如:Java、C、C++
Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法
4.在运行时获取泛型信息
5.在运行时调用任意一个对象的成员变量和方法
6.在运行时处理注解
7.生成动态代理
- package com.jiayifeng.java;
-
- import org.junit.Test;
-
- import java.lang.annotation.ElementType;
- import java.lang.reflect.Constructor;
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-16 15:18
- *
- * 一:反射
- * 疑问1:通过直接new的方式或反射的方式都可以调用公共的结构,开发中到底使用哪一个?
- * 建议:直接new的方式
- * 什么时候会使用反射的方式?
- * 反射的特征:动态性
- *
- * 疑问2:反射机制与面向对象中的封装性是不是矛盾的?如何看待这两个技术?
- * 不矛盾
- *
- * 二:关于java.lang.Class类的理解
- * 1.类的加载过程:
- * 程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)
- * 接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码
- * 文件加载到内存中。此过程就是类的加载。加载到内存中的类,我们就称之为运行时类,
- * 此运行时类,就作为Class的一个实例
- *
- * 2.换句话说,Class的实例就对应着一个运行时类
- *
- * 3.加载到内存中的运行时类,会缓存一定的时间。在此时间内,我们可以通过不同的方式来
- * 获取此运行时类
- */
- public class ReflectionTest {
- // 反射之前,对Person类的操作
- @Test
- public void test(){
- // 1.创建Person类的对象
- Person p1 = new Person("Tom",12);
-
- // 2.通过对象,调用其内部的属性、方法
- p1.age = 10;
- System.out.println(p1.toString());
- p1.show();
-
- // 在Person类外部,不可以通过Person类的对象调用其内部私有结构
- // 比如:name、showNation()、以及私有的构造器
- }
-
- // 反射之后,对Person类的操作
- @Test
- public void test1() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
- Class
clazz = Person.class; - // 1.通过反射,创建Person类的对象
- Constructor
cons = clazz.getConstructor(String.class, int.class); - Object obj = cons.newInstance("Tom",12);
- Person p = (Person)obj;
- System.out.println(p.toString());
- // 2.通过反射,调用对象指定的属性、方法
- // 调用属性
- Field age = clazz.getDeclaredField("age");
- age.set(p,10);
- System.out.println(p.toString());
-
- // 调用方法
- Method show = clazz.getDeclaredMethod("show");
- show.invoke(p);
-
- // 通过反射,可以调用Person类的私有结构的。比如:私有的构造器、方法、属性
- Constructor cons1 = clazz.getDeclaredConstructor(String.class);
- cons1.setAccessible(true);
- Person p1 = (Person)cons1.newInstance("Jerry");
- System.out.println(p1);
-
- // 调用私有属性
- Field name = clazz.getDeclaredField("name");
- name.setAccessible(true);
- name.set(p1,"hanmeimei");
- System.out.println(p1);
-
- // 调用私有方法
- Method showNation = clazz.getDeclaredMethod("showNation", String.class);
- showNation.setAccessible(true);
- String nation = (String) showNation.invoke(p1, "中国");//相当于String nation = p1.showNation("中国")
- System.out.println(nation);
- }
-
- @Test
- public void test2() throws ClassNotFoundException {
- // 获取Class的实例的方式
- // 方式一:调用运行时类的属性:.class
- Class clazz1 = Person.class;
- System.out.println(clazz1);
-
- // 方式二:通过运行时类的对象,调用getClass()
- Person p1 = new Person();
- Class clazz2 = p1.getClass();
- System.out.println(clazz2);
-
- // 方式三:调用Class的静态方法:forName(String classPath)(使用频率高)
- Class clazz3 = Class.forName("com.jiayifeng.java.Person");
- System.out.println(clazz3);
-
- System.out.println(clazz1 == clazz2);//true
- System.out.println(clazz1 == clazz3);//true
- System.out.println(clazz2 == clazz3);//ture
-
- // 方式四:使用类的加载器:ClassLoader(了解)
- ClassLoader classLoader = ReflectionTest.class.getClassLoader();
- Class clazz4 = classLoader.loadClass("com.jiayifeng.java.Person");
- System.out.println(clazz4);
- System.out.println(clazz1 == clazz4);
- }
-
- @Test
- public void test3(){
- Class c1 = Object.class;
- Class c2 = Comparable.class;
- Class c3 = String[].class;
- Class c4 = int[][].class;
- Class c5 = ElementType.class;
- Class c6 = Override.class;
- Class c7 = int.class;
- Class c8 = void.class;
- Class c9 = Class.class;
-
- int[] a = new int[10];
- int[] b = new int[100];
- Class c10 = a.getClass();
- Class c11 = b.getClass();
- // 只要数组的元素类型与维度一样,就是同一个Class
- System.out.println(c10 == c11);//true
-
- }
- }
- package com.jiayifeng.java;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-16 15:21
- */
- public class Person {
- private String name;
- public int age;
-
- public Person() {
- }
-
- public Person(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- private Person(String name) {
- this.name = name;
- }
-
- 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;
- }
-
- @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;
- }
- }
- package com.jiayifeng.java;
-
- import org.junit.Test;
-
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-16 16:44
- */
- public class ClassLoaderTest {
- @Test
- public void test1(){
- // 对于自定义类,使用系统类加载器进行加载
- ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
- System.out.println(classLoader);
-
- // 调用系统类加载器的getParent():获取扩展类加载器
- ClassLoader classLoader1 = classLoader.getParent();
- System.out.println(classLoader1);
-
- // 调用扩展类加载器的getParent():无法获取引导类加载器
- // 引导类加载器主要负责加载java的核心类库,无法加载自定义类的
- ClassLoader classLoader2 = classLoader1.getParent();
- System.out.println(classLoader2);
-
- ClassLoader classLoader3 = String.class.getClassLoader();
- System.out.println(classLoader3);
- }
-
- /*
- Properties:用来读取配置文件
- */
- @Test
- public void test2() throws IOException {
- Properties pros = new Properties();
- // 此时的文件默认在当前的module下
- // 读取配置文件的方式一:
- // FileInputStream fis = new FileInputStream("jdbc.properties");
- // pros.load(fis);
-
- // 读取配置文件的方式二:
- // 配置文件默认识别为:当前的module的src下
- 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);
- }
- }
- package com.jiayifeng.java;
-
- import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;
- import org.junit.Test;
-
- import java.util.Random;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-16 17:05
- *
- * 一:通过发射创建对应的运行时类的对象
- */
- public class NewInstanceTest {
- @Test
- public void test1() throws InstantiationException, IllegalAccessException {
- Class
clazz = Person.class; - // newInstance():调用此方法,创建对应的运行时类的对象
- // 内部调用了运行时类的空参的构造器
- /*
- 要想此方法正常的创建运行时类的对象,要求:
- 1.运行时类必须提供空参的构造器
- 2.空参的构造器的访问权限得够。通常,设置为public
- 在javabean中要求提供一个public的空参构造器。原因:
- 1.便于通过反射,创建运行时类的对象
- 2.便于子类继承此运行时类时,默认使用super()时,保证父类有此构造器
- */
- Person obj = clazz.newInstance();
- System.out.println(obj);
- }
-
- // 体会反射的动态性
- @Test
- public void test2(){
- for(int i = 0;i < 100;i++){
- int num = new Random().nextInt(3);//0 1 2
- String classPath = "";
- switch (num){
- case 0:
- classPath = "java.util.Date";
- break;
- case 1:
- classPath = "java.lang.Object";
- break;
- case 2:
- classPath = "com.jiayifeng.java.Person";
- break;
- }
-
- try {
- Object obj = getInstance(classPath);
- System.out.println(obj);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- // 创建一个指定类的对象。
- // ClassPath:指定类的全类名
- public Object getInstance(String classPath) throws Exception {
- Class clazz = Class.forName(classPath);
- return clazz.newInstance();
- }
- }
- package com.jiayifeng.java1;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 13:49
- */
- @MyAnnotation(value = "hi")
- public class Person extends Creature
implements Comparable,MyInterface{ - private String name;
- int age;
- public int id;
-
- public Person(){
-
- }
-
- @MyAnnotation(value = "abc")
- private Person(String name){
- this.name = name;
- }
-
- Person(String name,int age){
- this.name = name;
- this.age = age;
- }
-
- @MyAnnotation
- public String show(String nation){
- System.out.println("我的国籍是:" + nation);
- return nation;
- }
-
- public String display(String interests) throws Exception{
- return interests;
- }
- @Override
- public void info() {
- System.out.println("我是一个人");
- }
-
- @Override
- public int compareTo(String o) {
- return 0;
- }
- }
- package com.jiayifeng.java1;
-
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
-
- import static java.lang.annotation.ElementType.*;
- import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 13:59
- */
-
- @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
- @Retention(RetentionPolicy.RUNTIME)
- public @interface MyAnnotation {
- String value() default "hello";
- }
- package com.jiayifeng.java1;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 13:52
- */
- public interface MyInterface {
- void info();
- }
- package com.jiayifeng.java1;
-
- import java.io.Serializable;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 13:49
- */
- public class Creature
implements Serializable { - private char gender;
- public double weight;
-
- private void breate(){
- System.out.println("生物呼吸");
- }
-
- public void eat(){
- System.out.println("生物吃东西");
- }
- }
属性测试:
- package com.jiayifeng.java2;
-
- import com.jiayifeng.java1.Person;
- import org.junit.Test;
-
- import java.lang.reflect.Field;
- import java.lang.reflect.Modifier;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 14:03
- *
- * 一:获取当前运行时类的属性结构
- */
- public class FieldTest {
- @Test
- public void test(){
- Class clazz = Person.class;
-
- // 获取属性结构
- // getFields():获取当前运行时类及其父类中声明为public访问权限的属性
- Field[] fileds = clazz.getFields();
- for(Field f : fileds){
- System.out.println(f);
- }
- System.out.println();
- // public int com.jiayifeng.java1.Person.id
- // public double com.jiayifeng.java1.Creature.weight
-
- // getDeclaredFields():获取当前运行时类中声明的所有属性(不包含父类中声明的属性)
- Field[] declareFileds = clazz.getDeclaredFields();
- for(Field f : declareFileds){
- System.out.println(f);
- }
- // private java.lang.String com.jiayifeng.java1.Person.name
- // int com.jiayifeng.java1.Person.age
- // public int com.jiayifeng.java1.Person.id
- }
-
- @Test
- public void test1(){
- Class clazz = Person.class;
- Field[] declareFields = clazz.getDeclaredFields();
- for(Field f : declareFields){
- // 1.权限修饰符
- int modifiers = f.getModifiers();
- System.out.print(Modifier.toString(modifiers));
-
- // 2.数据类型
- Class type = f.getType();
- System.out.print(type.getName() + "\t");
-
- // 3.变量名
- String fName = f.getName();
- System.out.println(fName);
-
- System.out.println();
- }
- }
- }
方法测试:
- package com.jiayifeng.java2;
-
- import com.jiayifeng.java1.Person;
- import org.junit.Test;
-
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 14:21
- *
- * 一:获取运行时类的方法结构
- */
- public class MethodTest {
- @Test
- public void test1(){
- Class clazz = Person.class;
- // clazz.getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
- Method[] methods = clazz.getMethods();
- for(Method m : methods){
- System.out.println(m);
- }
- System.out.println();
-
- // getDeclaredMethods():获取当前运行时类中声明的所有方法(不包含父类中声明的方法)
- Method[] declaredMethods = clazz.getDeclaredMethods();
- for(Method m : declaredMethods){
- System.out.println(m);
- }
- }
-
- @Test
- public void test2(){
- Class clazz = Person.class;
- Method[] declaredMethods = clazz.getDeclaredMethods();
- for(Method m : declaredMethods){
- // 1.获取方法声明的注解
- Annotation[] annotations = m.getAnnotations();
- for(Annotation a :annotations){
- System.out.println(a);
- }
-
- // 2.权限修饰符
- System.out.print(Modifier.toString(m.getModifiers()) + "\t");
-
- // 3.返回值类型
- System.out.println(m.getReturnType().getName() + "\t");
-
- // 4.方法名
- System.out.println(m.getName());
-
- // 5.形参列表
- System.out.print("(");
- Class>[] parameterTypes = m.getParameterTypes();
- if (!(parameterTypes == null && parameterTypes.length == 0)) {
- for(int i = 0;i < parameterTypes.length;i++){
- if(i == parameterTypes.length - 1) {
- System.out.print(parameterTypes[i].getName() + "args_" + i);
- break;
- }
- System.out.println(parameterTypes[i].getName() + "args_" + i + ",");
- }
- }
- System.out.print(")");
-
- // 6.抛出的异常
- Class>[] exceptionTypes = m.getExceptionTypes();
- if(exceptionTypes.length > 0){
- System.out.print("throws:");
- for(int i = 0;i < exceptionTypes.length;i++){
- if(i == exceptionTypes.length - 1){
- System.out.print(exceptionTypes[i].getName());
- break;
- }
- System.out.print(exceptionTypes[i].getName() + ",");
- }
- }
- System.out.println();
-
- }
- }
- }
其它测试:
- package com.jiayifeng.java2;
-
- import com.jiayifeng.java1.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;
- import java.sql.SQLOutput;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 14:47
- */
- public class OtherTest {
- /*
- 获取构造器结构
- */
- @Test
- public void test1() {
- Class clazz = Person.class;
- // getConstructors():获取当前运行时类中声明为public的构造器
- Constructor[] constructors = clazz.getConstructors();
- for(Constructor c : constructors){
- System.out.println(c);
- }
- System.out.println();
-
- // getDeclaredConstructors():获取当前运行时类中声明的所有的构造器
- Constructor[] declaredConstructor = clazz.getDeclaredConstructors();
- for(Constructor c : declaredConstructor){
- System.out.println(c);
- }
- }
-
- /*
- 获取运行时的父类
- */
- @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 parameterizedType = (ParameterizedType) genericSuperclass;
- // 获取泛型类型
- Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
- System.out.println(actualTypeArguments[0].getTypeName());
-
- }
-
- /*
- 获取运行时类实现的接口
- */
- @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 : interfaces){
- System.out.println(c);
- }
- }
-
- /*
- 获取当前运行时类所在的包
- */
- @Test
- public void test6(){
- Class clazz = Person.class;
- Package aPackage = clazz.getPackage();
- System.out.println(aPackage);
- }
-
- /*
- 获取运行时类所声明的注解
- */
- @Test
- public void test7(){
- Class clazz = Person.class;
- Annotation[] annotations = clazz.getAnnotations();
- for(Annotation a : annotations){
- System.out.println(a);
- }
- }
- }
- package com.jiayifeng.java2;
-
- import com.jiayifeng.java1.Person;
- import org.junit.Test;
-
- import java.lang.reflect.Field;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 15:13
- *
- * 一:调用运行时类中指定的结构:属性、方法、构造器
- */
- public class ReflectionTest {
- @Test
- public void test1() throws InstantiationException, IllegalAccessException, NoSuchFieldException {
- Class clazz = Person.class;
- // 创建运行时类的对象
- Person p = (Person)clazz.newInstance();
- // 获取指定的属性:要求运行时类中的属性声明为public
- // 通常不采用此方法
- Field id = clazz.getField("id");
-
- /*
- 设置当前属性的值
- set():参数1:指明设置哪个对象的属性 参数2:将此属性值设置为多少
- */
- id.set(p,1001);
-
- /*
- 获取当前属性的值
- get():参数1:获取哪个对象的当前属性值
- */
- int Pid = (int)id.get(p);
- System.out.println(Pid);
- }
-
- /*
- 如何操作运行时类中的指定的属性
- */
- @Test
- public void test2() throws InstantiationException, IllegalAccessException, NoSuchFieldException {
- Class clazz = Person.class;
- // 创建运行时类的对象
- Person p = (Person)clazz.newInstance();
- // 1.getDeclaredField():获取运行时类中指定变量名的属性
- Field name = clazz.getDeclaredField("name");
-
- // 2.setAccessible():保证当前属性是可访问的
- name.setAccessible(true);
- // 3.获取、设置指定对象的此属性值
- name.set(p,"Tom");
- System.out.println(name.get(p));
- }
-
- /*
- 如何获取运行时类中的指定的方法
- */
- @Test
- public void test3() throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
- Class clazz = Person.class;
- // 创建运行时类的对象
- Person p = (Person)clazz.newInstance();
- // 1.获取指定的某个方法
- // getDeclaredMethod():参数1:指明获取的方法的名称 参数2:指明获取的方法的形参列表
- Method show = clazz.getDeclaredMethod("show", String.class);
- // 2.保证当前方法是可访问的
- show.setAccessible(true);
- // 3.调用方法invoke():参数1:方法的调用者 参数2:给方法形参赋值的实参
- // invoke()的返回值即为对应类中调用的方法的返回值
- Object returnValue = show.invoke(p, "CHN");
- System.out.println(returnValue);
-
- System.out.println("******如何调用静态方法*******");
- Method showDesc = clazz.getDeclaredMethod("showDesc");
- showDesc.setAccessible(true);
- // 如果调用的运行时类中的方法没有返回值,则此invoke()返回null
- Object returnVal = showDesc.invoke(Person.class);
- System.out.println(returnVal);
- }
-
- @Test
- public void test4(){
-
- }
- }
代理设计模式的原理:
使用一个代理将对象包装起来,然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理。代理对象决定是否以及何时将方法调用转到原始对象上
静态代理的特征:
代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理。最好可以通过一个代理类完成全部的代理功能
动态代理是指客户通过代理类来调用其它对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象
动态代理的使用场合 :
调试
远程方法调用
- package com.jiayifeng.java3;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 18:52
- *
- * 一:静态代理举例
- * 特点:代理类和被代理类在编译期间就确定下来了
- */
- interface ClothFactory{
- void produceCloth();
- }
-
- //代理类
- class ProxyClothFactory implements ClothFactory{
- private ClothFactory factory;
-
- public ProxyClothFactory(ClothFactory factory){
- this.factory = factory;
- }
-
-
- @Override
- public void produceCloth() {
- System.out.println("代理工厂做一些准备工作");
-
- factory.produceCloth();
-
- System.out.println("代理工厂做一些后续的收尾工作");
- }
- }
-
- //被代理类
- class NikeClothFactory implements ClothFactory{
-
- @Override
- public void produceCloth() {
- System.out.println("Nike工厂生产一批运动服");
- }
- }
- public class StaticProxyTest {
- public static void main(String[] args) {
- // 创建被代理类的对象
- NikeClothFactory nike = new NikeClothFactory();
- // 创建代理类的对象
- ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nike);
-
- proxyClothFactory.produceCloth();
- }
-
- }
-
-
-
- package com.jiayifeng.java3;
-
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- import java.lang.reflect.Proxy;
-
- /**
- * author 爱编程的小贾
- * create 2023-10-18 19:06
- *
- * 一:动态代理的举例
- */
- interface Human{
- String getBelief();
- void eat(String food);
- }
-
- //被代理类
- class SuperMan implements Human{
-
-
- @Override
- public String getBelief() {
- return "I belive I can fly!";
- }
-
- @Override
- public void eat(String food) {
- System.out.println("我喜欢吃" + food);
- }
- }
-
- /*
- 要想实现动态代理,需要解决的问题?
- 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象
- 问题二:当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法
- */
- class ProxyFactory{
- // 调用此方法,返回一个代理类的对象。解决问题一
- public static Object getProxyInstance(Object obj){//obj:被代理类的对象
- MyInvocationHandler handler = new MyInvocationHandler();
-
- handler.bind(obj);
-
- return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
- obj.getClass().getInterfaces(),handler);
- }
- }
-
- class MyInvocationHandler implements InvocationHandler{
- private Object obj;//赋值时也需要使用被代理类的对象进行赋值
-
- public void bind(Object obj){
- this.obj = obj;
- }
- // 当我们通过代理类的对象,调用方法a时,就会自动的调用如下的方法:invoke()
- // 将被代理类要执行的方法a的功能就声明在invoke()中
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- // method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
- // obj:被代理类的对象
- Object returnValue = method.invoke(obj, args);
- // 上述方法的返回值就作为当前类中的invoke()的返回值
- return returnValue;
- }
- }
- public class ProxyTest {
- public static void main(String[] args) {
- SuperMan superMan = new SuperMan();
- Human proxyInstance = (Human)ProxyFactory.getProxyInstance(superMan);
- // 当通过代理类对象调用方法时,会自动的调用被代理类中同名的方法
- String belief = proxyInstance.getBelief();
- System.out.println(belief);
- proxyInstance.eat("四川麻辣烫");
- System.out.println("***************");
-
- NikeClothFactory nikeClothFactory = new NikeClothFactory();
- ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
- proxyClothFactory.produceCloth();
- }
- }