平常写代码注意的细节part7(反射机制)P636-P665

学习内容

在这里插入图片描述

1. 反射机制概述

在这里插入图片描述

在这里插入图片描述

file:///E:/download/2019Java%E5%B0%9A%E7%A1%85%E8%B0%B7%E5%85%A8%E5%A5%97%E6%95%99%E7%A8%8B/1_%E8%AF%BE%E4%BB%B6/%E7%AC%AC2%E9%83%A8%E5%88%86%EF%BC%9AJava%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B/%E5%B0%9A%E7%A1%85%E8%B0%B7_%E5%AE%8B%E7%BA%A2%E5%BA%B7_%E7%AC%AC15%E7%AB%A0_Java%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6/%E5%B0%9A%E7%A1%85%E8%B0%B7_%E5%AE%8B%E7%BA%A2%E5%BA%B7_%E7%AC%AC15%E7%AB%A0_Java%E5%8F%8D%E5%B0%84%E6%9C%BA%E5%88%B6.pdf

在这里插入图片描述

Person Dog类又可看做Class类的实例

Class的理解

Class也是一个类,他的实例对应着一个运行时类,他也是反射机制的源头,通过他可以动态地调用运行时类的各个结构:属性、方法、构造器 、注解、接口、父类、…

●Java反射机制提供的功能

➢在运行时判断任意-一个对象所属的类
➢在运行时构造任意--个类的对象
➢在运行时判断任意-一个类所具有的成员变量和方法
➢在运行时获取泛型信息
➢在运行时调用任意-一个对象的成员变量和方法
➢在运行时处理注解
➢生成动态代理

2. 一个反射的例子

Person.java

public class Person {

    private String name;
    public int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + 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(String name, int age) {

        this.name = name;
        this.age = age;
    }

    private Person(String name) {
        this.name = name;
    }

    public Person() {
        System.out.println("Person()");
    }

    public void show(){
        System.out.println("你好,我是一个人");
    }

    private String showNation(String nation){
        System.out.println("我的国籍是:" + nation);
        return nation;
    }
}

反射之前,对于Person的操作

    @Test
    public void test1() {
        //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 test2() throws Exception{
        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);

        System.out.println("*******************************");

        //通过反射,可以调用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);
    }

启发

   疑问1:通过直接new的方式或反射的方式都可以调用公共的结构,开发中到底用那个?
   建议:直接new的方式。
   什么时候会使用:反射的方式。 反射的特征:动态性
   疑问2:反射机制与面向对象中的封装性是不是矛盾的?如何看待两个技术?
   不矛盾。
    关于java.lang.Class类的理解
    1.类的加载过程:
    程序经过javac.exe命令以后,会生成一个或多个字节码文件(.class结尾)。
    接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件
    加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此
    运行时类,就作为Class的一个实例。

    2.换句话说,Class的实例就对应着一个运行时类。
    3.加载到内存中的运行时类,会缓存一定的时间。在此时间之内,我们可以通过不同的方式
    来获取此运行时类。

    获取Class的实例的方式(前三种方式需要掌握)

获取Class实例的方式

工作中方式3用的更多,更能体现动态性

    @Test
    public void test3() throws ClassNotFoundException {
        //方式一:调用运行时类的属性:.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.atguigu.java.Person");
//        clazz3 = Class.forName("java.lang.String");
        System.out.println(clazz3);

        System.out.println(clazz1 == clazz2); //true
        System.out.println(clazz1 == clazz3); //true

        //方式四:使用类的加载器:ClassLoader  (了解)
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("com.atguigu.java.Person");
        System.out.println(clazz4);

        System.out.println(clazz1 == clazz4);
    }

Class实例可以是哪些结构的说明

只要数组的元素类型与维度一样,就是同一个Class

    @Test
    public void test4(){
        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);
    }

理解类的加载器(P645、646不太懂)

在这里插入图片描述
在这里插入图片描述

    @Test
    public void test1(){
        //对于自定义类,使用系统类加载器进行加载
        ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
        System.out.println(classLoader); //sun.misc.Launcher$AppClassLoader@18b4aac2
        //调用系统类加载器的getParent():获取扩展类加载器
        ClassLoader classLoader1 = classLoader.getParent();
        System.out.println(classLoader1); // sun.misc.Launcher$ExtClassLoader@452b3a41
        //调用扩展类加载器的getParent():无法获取引导类加载器
        //引导类加载器主要负责加载java的核心类库,无法加载自定义类的。
        ClassLoader classLoader2 = classLoader1.getParent(); 
        System.out.println(classLoader2); // null

        ClassLoader classLoader3 = String.class.getClassLoader();
        System.out.println(classLoader3); // null
    }

Properties类读取配置文件

新建一个property文件,需要右键新建的是bundel
两种方式的文件路径不一样需要注意
Properties bundel中的key value 都默认的是string
Properties pros = new Properties();的实例pros.load()是一个void方法

方法一: Properties
方法二:ClassLoaderTest.class.getClassLoader (public类的)
在这里插入图片描述

public class ClassLoaderTest {
    @Test
    public void test2() throws Exception {

        Properties pros =  new Properties();
        //此时的文件默认在当前的module下。
        //读取配置文件的方式一:
//        FileInputStream fis = new FileInputStream("jdbc.properties");
//        FileInputStream fis = new FileInputStream("src\\jdbc1.properties");
//        pros.load(fis);

        //读取配置文件的方式二:使用ClassLoader
        //配置文件默认识别为:当前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);
    }
}

3. 通过反射Class的实例,创建运行时类的对象

Class<Person> clazz = Person.class;
当加上泛型后,生成对象的时候自动识别为<Person>而不是Object,不用强制转换了


        newInstance():调用此方法,创建对应的运行时类的对象。内部调用了运行时类的空参的构造器。

        要想此方法正常的创建运行时类的对象,要求:
        1.运行时类必须提供空参的构造器
        2.空参的构造器的访问权限得够。通常,设置为public。

        在javabean中要求提供一个public的空参构造器。原因:
        1.便于通过反射,创建运行时类的对象
        2.便于子类继承此运行时类时,默认调用super()时,保证父类有此构造器

     
    @Test
    public void test1() throws IllegalAccessException, InstantiationException {
        Class<Person> clazz = Person.class;

        Person obj = clazz.newInstance();
        System.out.println(obj);

    }

4. 获取运行时类的完整结构(day11)

4.1获取运行时类的属性结构

getDeclaredFields();只能获取当前类的属性

    public void test2(){
        Class clazz = Person.class;
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field f : declaredFields){
            //1.权限修饰符
            int modifier_ = f.getModifiers();
            System.out.print(modifier_+"\t");
            int modifier = f.getModifiers();
            System.out.print(Modifier.toString(modifier) + "\t");  //java.lang.reflect

            //2.数据类型
            Class type = f.getType();
            System.out.print(type.getName() + "\t");

            //3.变量名
            String fName = f.getName();
            System.out.print(fName);
            System.out.println();
        }
    }

output

2	private	java.lang.String	name
0		int	age  //(default省略了)
1	public	int	id

getFields(),获取当前运行时类及其父类中声明为public访问权限的属性

    @Test
    public void test1(){
        Class clazz = Person.class;
        //获取属性结构
        //getFields():获取当前运行时  类 and 父类中声明为public访问权限的属性
        Field[] fields = clazz.getFields();
        for(Field f : fields){
            System.out.println(f);
        }
        System.out.println();
        //getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
        Field[] declaredFields = clazz.getDeclaredFields();
        for(Field f : declaredFields){
            System.out.println(f);
        }
    }

output

public int com.atguigu.java1.Person.id
public double com.atguigu.java1.Creature.weight

private java.lang.String com.atguigu.java1.Person.name
int com.atguigu.java1.Person.age
public int com.atguigu.java1.Person.id

4.2 获取运行时类的方法结构

注解+反射+设计模式=框架

    @Test
    public void test1(){
        Class clazz = Person.class;
        //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);
        }
    }

output

public java.lang.String com.atguigu.java1.Person.toString()
public int com.atguigu.java1.Person.compareTo(java.lang.String)
public int com.atguigu.java1.Person.compareTo(java.lang.Object)
public void com.atguigu.java1.Person.info()
public java.lang.String com.atguigu.java1.Person.display(java.lang.String,int) throws java.lang.NullPointerException,java.lang.ClassCastException
public void com.atguigu.java1.Creature.eat()
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

public java.lang.String com.atguigu.java1.Person.toString()
public int com.atguigu.java1.Person.compareTo(java.lang.String)
public int com.atguigu.java1.Person.compareTo(java.lang.Object)
private static void com.atguigu.java1.Person.showDesc()
public void com.atguigu.java1.Person.info()
private java.lang.String com.atguigu.java1.Person.show(java.lang.String)
public java.lang.String com.atguigu.java1.Person.display(java.lang.String,int) throws java.lang.NullPointerException,java.lang.ClassCastException
    @Xxxx
    权限修饰符  返回值类型  方法名(参数类型1 形参名1,...) throws XxxException{}

    @Test
    public void test2(){
        Class clazz = Person.class;
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for(Method m : declaredMethods){
            //1.获取方法声明的注解,注意SOURCE RUNTIME CLASS的生命周期问题,只有RUNTIME可以通过反射获取到
            Annotation[] annos = m.getAnnotations();
            for(Annotation a : annos){
                System.out.println(a);
            }

            //2.权限修饰符
            System.out.print(Modifier.toString(m.getModifiers()) + "\t");

            //3.返回值类型
            System.out.print(m.getReturnType().getName() + "\t");

            //4.方法名
            System.out.print(m.getName());
            System.out.print("(");
            //5.形参列表
            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.print(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();
        }
    }

output

public	java.lang.String	toString()
public	int	compareTo(java.lang.String args_0)
public volatile	int	compareTo(java.lang.Object args_0)
public	void	info()
@com.atguigu.java1.MyAnnotation(value=hello)
private	java.lang.String	show(java.lang.String args_0)
public	java.lang.String	display(java.lang.String args_0,int args_1)throws java.lang.NullPointerException,java.lang.ClassCastException
private static	void	showDesc()

4.3 获取运行时类的构造器

    @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[] declaredConstructors = clazz.getDeclaredConstructors();
        for(Constructor c : declaredConstructors){
            System.out.println(c);
        }
    }

output

public com.atguigu.java1.Person()

com.atguigu.java1.Person(java.lang.String,int)
private com.atguigu.java1.Person(java.lang.String)
public com.atguigu.java1.Person()

4.4 获取运行时父类\父类的泛型\仅泛型

    @Test
    public void test2(){
        Class clazz = Person.class;
        Class superclass = clazz.getSuperclass();
        System.out.println(superclass); // class com.atguigu.java1.Creature
    }

    @Test
    public void test3(){
        Class clazz = Person.class;
        Type genericSuperclass = clazz.getGenericSuperclass();
        System.out.println(genericSuperclass); // com.atguigu.java1.Creature<java.lang.String>
    }

    @Test
    public void test4(){
        Class clazz = Person.class;
        //Type 是一个接口
        Type genericSuperclass = clazz.getGenericSuperclass();
        System.out.println(genericSuperclass); // com.atguigu.java1.Creature<java.lang.String>
        ParameterizedType paramType = (ParameterizedType) genericSuperclass; //带参数的类型 ,泛型的参数
        //获取泛型类型
        Type[] actualTypeArguments = paramType.getActualTypeArguments();
        System.out.println(actualTypeArguments[0]); // class java.lang.String
        System.out.println(actualTypeArguments[0].getTypeName()); // java.lang.String
        System.out.println(((Class)actualTypeArguments[0]).getName()); // java.lang.String
    }

4.5 获取运行时类实现的接口

    @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);
        }
    }

output

interface java.lang.Comparable
interface com.atguigu.java1.MyInterface

interface java.io.Serializable

4.6 获取运行时类所在的包

    @Test
    public void test6(){
        Class clazz = Person.class;
        Package pack = clazz.getPackage();
        System.out.println(pack); // package com.atguigu.java1
    }

4.7 获取运行时类声明的注解

    @Test
    public void test7(){
        Class clazz = Person.class;
        Annotation[] annotations = clazz.getAnnotations();
        for(Annotation annos : annotations){
            System.out.println(annos); // @com.atguigu.java1.MyAnnotation(value=hi)
        }
    }

5. 调用运行时类的制定结构(重点)

主要还是------ 属性方法构造器

5.1 属性

方法一:不需要掌握

    @Test
    public void testField() throws Exception {
        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 testField1() throws Exception {
        Class clazz = Person.class;

        //创建运行时类的对象
        Person p = (Person) clazz.newInstance();

        //1. getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
        Field name = clazz.getDeclaredField("name");

        //2.保证当前属性是可访问的
        name.setAccessible(true);
        //3.获取、设置指定对象的此属性值
        name.set(p,"Tom"); //静态属性 name.set(Person.class,"Tom");
		或name.set(null,"Tom"); //此时第一个参数不重要,因为已经知道是那个类,又是静态的属性
        System.out.println(name.get(p));
    }

5.2 方法、静态方法

    如何操作运行时类中的指定的方法 -- 需要掌握
    非静态的代码-必须有运行时的对象

1.获取指定的某个方法
2.保证当前方法是可访问的 	show.setAccessible(true);
3. 调用方法的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参
        invoke()的返回值即为对应类中调用的方法的返回值。
如果调用的运行时类中的方法没有返回值,则此invoke()返回null
    @Test
    public void testMethod() throws Exception {
        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"); //String nation = p.show("CHN");
        System.out.println(returnValue);

        System.out.println("*************如何调用静态方法*****************");

        // private static void showDesc()

        Method showDesc = clazz.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
        //如果调用的运行时类中的方法没有返回值,则此invoke()返回null
//        Object returnVal = showDesc.invoke(null);
        Object returnVal = showDesc.invoke(Person.class);
        System.out.println(returnVal);//null
    }

output

我的国籍是:CHN
CHN
*************如何调用静态方法*****************
我是一个可爱的人
null

5.3 调用运行时类中的制定构造器

Person obj = clazz.newInstance();方式的空参构造器更常用

    @Test
    public void testConstructor() throws Exception {
        Class clazz = Person.class;
        //private Person(String name)
        /*
        1.获取指定的构造器
        getDeclaredConstructor():参数:指明构造器的参数列表
         */
        Constructor constructor = clazz.getDeclaredConstructor(String.class);

        //2.保证此构造器是可访问的
        constructor.setAccessible(true);

        //3.调用此构造器创建运行时类的对象   Person obj = clazz.newInstance();更常用
        Person per = (Person) constructor.newInstance("Tom");
        System.out.println(per);
    }

6. 反射的应用:动态代理

先看一个静态代理

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) {
        //创建被代理类的对象
        ClothFactory nike = new NikeClothFactory();
        //创建代理类的对象
        ClothFactory proxyClothFactory = new ProxyClothFactory(nike);
        proxyClothFactory.produceCloth();
    }
}

动态代理

interface Human{
    String getBelief();
    void eat(String food);
}
//被代理类
class SuperMan implements Human{
    @Override
    public String getBelief() {
        return "I believe I can fly!";
    }
    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃" + food);
    }
}
class HumanUtil{
    public void method1(){
        System.out.println("====================通用方法一====================");
    }
    public void method2(){
        System.out.println("====================通用方法二====================");
    }
}
/*
要想实现动态代理,需要解决的问题?
问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象。
问题二:当通过代理类的对象调用方法a时,如何动态的去调用被代理类中的同名方法a。
 */

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 {
        HumanUtil util = new HumanUtil();
        util.method1();
        //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
        //obj:被代理类的对象
        Object returnValue = method.invoke(obj,args);
        util.method2();
        //上述方法的返回值就作为当前类中的invoke()的返回值。
        return returnValue;

    }
}

public class ProxyTest {
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //proxyInstance:代理类的对象
        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();
    }
}

AOP(Aspect Oriented Programming) 面向切面编程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值