反射与动态代理


反射

Java反射机制提供的功能

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

public class Person {
    public String name;
    private int age;

    public Person() {
    }

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

    public Person(String name, int age) {
        this.name = name;
        this.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;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
    public void show(){
        System.out.println("hello");
    }

    private void test(){
        System.out.println("test reflect");
    }
}


package reflect01;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test01 {

    @Test
    public void test1() throws Exception {
        Constructor<Person> constructor = Person.class.getConstructor(String.class, int.class);
        Person tom = constructor.newInstance("tom", 12);
        System.out.println(tom.toString());
    }

    @Test
    public void test12() throws Exception {
        Constructor<Person> constructor = Person.class.getConstructor(String.class, int.class);
        Person tom = constructor.newInstance("tom", 12);
        Field name = Person.class.getDeclaredField("name");
        name.set(tom, "hhh");
        System.out.println(tom.toString());
    }

    //调方法
    @Test
    public void test3() throws Exception {
        Class<Person> aClass = Person.class;
        Constructor<Person> constructor = aClass.getConstructor(String.class, int.class);
        Person tom = constructor.newInstance("tom", 12);
        Method show = Person.class.getMethod("show");
        show.invoke(tom);

//调用私有构造函数
        System.out.println("----------------------------------------------");
        Constructor<Person> constructor1 = aClass.getDeclaredConstructor(String.class);
        constructor1.setAccessible(true);
        Person test = constructor1.newInstance("test");
        System.out.println(test.toString());

        //调用私有属性
        Field age = aClass.getDeclaredField("age");
        age.setAccessible(true);
        age.set(test,11);
        System.out.println(test.toString());

        //调用私有方法
        Method method = aClass.getDeclaredMethod("test");
        method.setAccessible(true);
        method.invoke(test);
    }

    /**
     * 反射是否与类的封装是矛盾的?
     */
}

获取Class实例

 //获取Class类方式
    @Test
    public void test4() throws Exception {
        Class aClass = Person.class;
        System.out.println(aClass);


        Person person = new Person();
        Class aClass1 = person.getClass();

        Class aClass2 = Class.forName("reflect01.Person");

        System.out.println(aClass==aClass1);

        ClassLoader classLoader = Test01.class.getClassLoader();
        Class aClass3 = classLoader.loadClass("reflect01.Person");

    }

获取运行时类的信息

package reflect02;

import java.io.StringReader;
import java.util.Comparator;

@MyAnnotation(value = "123")
public class Person extends Creature<String>  implements Comparable<String>, MyInterface{

    public static int fie=2;
    private String name;
    int age;
    public int id;

    public Person() {
    }

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

     Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    @MyAnnotation
    private String show(String nation){
        System.out.println("国籍"+nation);
        return  nation;

    }

    public String display(String interests){
        return interests;
    }

    public void info(){
            System.out.println("我是人");
        }

    @Override
    public int compareTo(String o) {
        return 0;
    }

    public static void me(String s){
        System.out.println(s);
    }
}
package reflect02;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
public class Test {
    /**
     * 获取类属性结构
     */
    @org.junit.Test
    public void test(){
        Class<Person> aClass = Person.class;
        //获取运行时类及其父类声明为public的属性
        Field[] fields = aClass.getFields();
        for (Field f:fields) {
            System.out.println(f);
        }
        System.out.println();
//获取当前运行时类的属性  不包括父类的属性
        Field[] fields1 = aClass.getDeclaredFields();
        for (Field f:fields1) {
            System.out.println(f);
        }
    }


    @org.junit.Test
    public void test1(){
        Class<Person> aClass = Person.class;
        //获取运行时类及其父类声明为public的属性
        Field[] fields = aClass.getFields();
        for (Field f:fields) {

            /**
             * 获取权限修饰符
             * 默认权限也是权限
             */
            int modifiers = f.getModifiers();
            System.out.println(Modifier.toString(modifiers));
            //数据类型
            Class type = f.getType();
            System.out.println(type);
            //变量名
            String name = f.getName();
            System.out.println(name);
        }
    }

    /**
     * 获取运行时类的方法结构
     */
    @org.junit.Test
    public void test2(){
        Class<Person> aClass = Person.class;
        //获取运行时类及其父类声明为public的方法
        Method[] methods = aClass.getMethods();
        for (Method me :
                methods) {
            System.out.println(me);
        }
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method me :
                declaredMethods) {
            System.out.println(me);
        }
    }

    /**
     * 获取方法的内部结构
     */
    @org.junit.Test
    public void test3(){
       //获取方法声明的注解
        Class<Person> aClass = Person.class;
        Method[] methods = aClass.getDeclaredMethods();
        for (Method me:methods){
            Annotation[] annotations = me.getAnnotations();
            for (Annotation an:
                 annotations) {
                System.out.println(an);
            }
            //权限修饰符
            int modifiers = me.getModifiers();
            System.out.println(Modifier.toString(modifiers));
         //返回值类型
            String name = me.getReturnType().getName();
            System.out.println(name);
            //方法名
            String name1 = me.getName();
            System.out.println(name1);
            //抛出的异常
            Class<?>[] exceptionTypes = me.getExceptionTypes();
        }
    }

    /**
     * 获取构造器
     */
    @org.junit.Test
    public void test4(){
        Class<Person> personClass = Person.class;
        //当前运行时类中声明为public的构造器
        Constructor<?>[] constructors = personClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        //拿到运行时类中所有的构造器
        Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
    }

    /**
     * 获取运行时类的父类
     */
    @org.junit.Test
    public void test5(){
        //获取运行时类的父类
        Class<Person> personClass = Person.class;
        Class<? super Person> superclass = personClass.getSuperclass();
        System.out.println(superclass);

        //获取运行时类带泛型的父类
        Type genericSuperclass = personClass.getGenericSuperclass();
        System.out.println(genericSuperclass);
    }

    /**
     * 获取运行时类实现的接口
     */
    @org.junit.Test
    public void test6() {
        Class<Person> personClass = Person.class;
        Class<?>[] interfaces = personClass.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println(anInterface);
        }
    }
    /**
     * 获取运行是类所在的包
     */
    @org.junit.Test
    public void test7() {
        Class<Person> personClass = Person.class;
        Package aPackage = personClass.getPackage();
        System.out.println(aPackage);
    }
}
package reflect02;

import org.junit.Test;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
 * 调用运行时类中制定的结构 属性  方法  构造器
 */
public class Test2 {
    @Test
    public void test() throws Exception{
        Class<Person> personClass = Person.class;

        Person person = personClass.newInstance();
        //获取public的属性
        Field id = personClass.getField("id");
        id.set(person,100);
        System.out.println(id.get(person));
    }
    @Test
    public void test1() throws Exception{
        Class<Person> personClass = Person.class;

        Person person = personClass.newInstance();
//可以获取为private属性  但要设置access
        Field age = personClass.getDeclaredField("age");
        Field name = personClass.getDeclaredField("name");
        age.set(person,12);
        System.out.println(age.get(person));

        name.setAccessible(true);
        name.set(person,"sss");
        System.out.println(name.get(person));

    }
    /**
     * 获取运行时类指定的方法
     *
     */
    @Test
    public void test2() throws Exception{
        Class<Person> personClass = Person.class;
        Person person = personClass.newInstance();
        //指明方法名称  指明形参列表
        Method show = personClass.getDeclaredMethod("show", String.class);
        show.setAccessible(true);
        show.invoke(person,"CHN");
        //调用静态方法
        Method me = personClass.getDeclaredMethod("me",String.class);
        me.setAccessible(true);
        me.invoke(person,"ss");
//调用静态属性
        Field fie = personClass.getField("fie");
        System.out.println(fie.get(person));
    }
}

静态代理

假设现在项目经理有一个需求:在项目现有所有类的方法前后打印日志。

你如何在不修改已有代码的前提下,完成这个需求?

我首先想到的是静态代理。具体做法是:

1.为现有的每一个类都编写一个对应的代理类,并且让它实现和目标类相同的接口(假设都有)

2.在创建代理对象时,通过构造器塞入一个目标对象,然后在代理对象的方法内部调用目标对象同名方法,并在调用前后打印日志。也就是说,代理对象 = 增强代码 + 目标对象(原对象)。有了代理对象后,就不用原对象了

package proxy;

interface Factory{
    public void produceCloth();
}

class ProxyCloth implements  Factory{
    public Factory factory;

    public ProxyCloth(Factory factory) {
        this.factory = factory;
    }
    @Override
    public void produceCloth() {
        System.out.println("生产衣服前的准备");
        factory.produceCloth();
        System.out.println("生产衣服后的准备");

    }
}
//被代理类
class Nike implements  Factory{
    @Override
    public void produceCloth() {
        System.out.println("耐克衣服");
    }
}

public class StaticProxy {
    public static void main(String[] args) {
        Nike nike = new Nike();
        ProxyCloth proxyCloth = new ProxyCloth(nike);
        proxyCloth.produceCloth();
    }
}

动态代理

区分代理类 和被代理类

如明星和经纪人 明星是作为被代理类 经纪人是作为代理类

package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

interface Human{
    String getBelief();
    void eat(String fool);
}

class SuperMan implements  Human{
    @Override
    public String getBelief() {
        return "Java";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃"+food);
    }
}

/**
 * 动态代理解决的问题?
 * 1.如何根据加载到内存中的被代理类  动态的创建一个代理类及其对象
 * 2.当通过代理类的对象调用方法时  如何动态的去调用被代理类的同名方法
 */

class ProxyFactory{

    //返回一个代理类的对象
    public static Object getProxyInstance(Object object){  //传进去被代理类的对象  动态生产一个代理类的对象
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
        myInvocationHandler.bind(object);
        Object o = java.lang.reflect.Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), myInvocationHandler);
        return o;
    }
}

class   MyInvocationHandler implements InvocationHandler{
    private Object obj;
    public void bind(Object obj){
        this.obj=obj;
    }
    //当通过代理类的对象 调用方法a是  会就自动调用如下方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      //为代理类对象调用的方法  此方法也就作为了被代理类对象要调用的方法
        Object invoke = method.invoke(obj, args);
        //返回方法返回值
        return invoke;
    }
}
public class Proxy {
    public static void main(String[] args) {

        SuperMan superMan = new SuperMan();
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        proxyInstance.eat("零食");
        System.out.println(proxyInstance.getBelief());
        Nike nike = new Nike();
        Factory proxyInstance1 = (Factory) ProxyFactory.getProxyInstance(nike);
        proxyInstance1.produceCloth();
    }
}

根据代理Class的构造器创建对象时,需要传入InvocationHandler。通过构造器传入一个引用,那么必然有个成员变量去接收。没错,代理对象的内部确实有个成员变量invocationHandler,而且代理对象的每个方法内部都会调用handler.invoke()!InvocationHandler对象成了代理对象和目标对象的桥梁,不像静态代理这么直接。


文章作者: 蛰伏
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 蛰伏 !
  目录