Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的法的功能称为java语言的反射机制。

反射机制:具有操作字节码文件的能力

  1. java.lang.Class :保留一个类的全部信息
  2. java.util.reflect.Constructor:保存了一个类当中的构造方法的所有信息
  3. java.util.reflect.Method:保存了一个类当中的方法的所有信息
  4. java.util.reflect.Field:保存了一个类当中的成员属性的所有信息

动态代理

动态代理简单来说就是在程序执行过程中,创建代理对象,通过代理对象执行方法,给目标类的方法增加额外的功能,也叫做功能增强。

JDK动态代理的实现步骤

  1. 首先我们需要有一个目标类,在目标类的基础上通过动态代理实现功能增强
  2. 创建InvocationHandler接口的实现类,在这个类中实现invoke方法,在invoke方法中实现给目标类的方法增强功能
  3. 通过JDK中的Proxy创建代理,通过代理调用目标类中的方法,实现功能增强

JDK动态代理的代码实现

  1. 创建一个接口
public interface SomeService {
    void doSome();
    void doOther();
}
  1. 目标类实现这个接口:
public class SomeServiceImpl implements SomeService {

    @Override
    public void doSome() {
        System.out.println("执行doSome");
    }

    @Override
    public void doOther() {
        System.out.println("执行doOther");
    }
}
  1. 创建一个工具类,里面是增强的功能:
public class ServiceTools {

    public static void doLog(){
        System.out.println("方法的执行时间:" + new Date());
    }

    public static void doTrans(){
        System.out.println("方法执行完毕,提交事务");
    }

}
  1. 创建InvocationHandler接口的实现类
public class MyInvocationHandler implements InvocationHandler {
    //目标对象
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    //通过代理对象执行方法时,会调用执行这个invoke()方法

    /**
     *
     * @param proxy 代理类实例
     * @param method 被代理的方法
     * @param args 方法的参数数组
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("执行MyInvocationHandler中的invoke方法");

        //打印被调用的目标类中的方法名
        System.out.println(method.getName());

        Object res = null;

        //实现的增强的功能
        ServiceTools.doLog();

        //执行目标类方法,通过Method实现
        res = method.invoke(target, args);

        //增强的功能
        ServiceTools.doTrans();

        //返回目标方法的执行结果
        return res;
    }
}
  1. 通过Proxy创建代理
public static void main(String[] args) {
        //创建目标对象
        SomeService target = new SomeServiceImpl();

        //创建InvocationHandler对象
        InvocationHandler handler = new MyInvocationHandler(target);

        //使用Proxy创建代理
        SomeService proxy = (SomeService) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                handler
        );

        //通过代理执行方法,会调用handle中的invoke()方法
        proxy.doSome();
    }

通用类:

public class JdkProxy implements InvocationHandler {

    private Object target;

    public JdkProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long starTime = System.nanoTime();
        Object result = method.invoke(this.target, args);
        long endTime = System.nanoTime();
        System.out.println(this.target.getClass() + ".m1()方法耗时(纳秒):" + (endTime - starTime));
        return result;
    }

    /**
     * 用来创建targetInterface接口的代理对象
     *
     * @param target          需要被代理的对象
     * @param targetInterface 被代理的接口
     * @param <T>
     * @return
     */
    public static <T> T createProxy(Object target, Class<T> targetInterface) {
        if (!targetInterface.isInterface()) {
            throw new IllegalStateException("targetInterface必须是接口类型!");
        } else if (!targetInterface.isAssignableFrom(target.getClass())) {
            throw new IllegalStateException("target必须是targetInterface接口的实现类!");
        }
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JdkProxy(target));
    }

    public static <T> T createProxy(Object target) {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new JdkProxy(target));
    }
}

使用:
IService proxy = JdkProxy.createProxy(new SomeServiceImpl(), SomeService.class);

IService proxy1 = JdkProxy.createProxy(new SomeServiceImpl());

总结一下动态代理实现过程:

  1. 通过getProxyClass0()生成代理类。
  2. 通过Proxy.newProxyInstance()生成代理类的实例对象,创建对象时传入InvocationHandler类型的实例。
  3. 调用新实例的方法,即此例中的m1(),m2(),即原InvocationHandler类中的invoke()方法。

动态代理的作用:

  1. 在目标类源代码不改变的情况下,增加目标类的功能
  2. 当涉及到多个方法都需要增加某些同样的功能时,使用动态代理可以减少代码的重复
  3. 可以使目标类专注于业务逻辑代码
  4. 实现解耦合,让业务功能和日志、事务和非事务功能分离

为什么jdk动态代理必须实现接口:

 //反编译出来看,继承了Proxy类,所以没法再继承了,java是单继承
String path = "logs/$Proxy0.class";
byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0",
IServiceImpl.class.getInterfaces());

FileOutputStream out = new  FileOutputStream(path);
out.write(classFile);
out.flush();
out.close();

cglib

 public static void main(String[] args) {
        //使用Enhancer来给某个类创建代理类,步骤

        //1.创建Enhancer对象
        Enhancer enhancer = new Enhancer();
        //2.通过setSuperclass来设置父类型,即需要给哪个类创建代理类
        enhancer.setSuperclass(Service1.class);
        /*
        3.设置回调,需实现org.springframework.cglib.proxy.Callback接口,
        此处我们使用的是org.springframework.cglib.proxy.MethodInterceptor,
        也是一个接口,实现了Callback接口,
        当调用代理对象的任何方法的时候,都会被MethodInterceptor接口的invoke方法处理
        */
        /**
         * 此处
         *  1. MethodInterceptor 拦截所有方法
         *  2. 拦截所有方法并返回自定义的值(FixedValue)
         *  3. 直接放行,不做任何操作(NoOp.INSTANCE)
         *  4. 不同的方法使用不同的拦截器(CallbackFilter)
         * */
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                /**
                 * 代理对象方法拦截器
                 * @param o 代理对象
                 * @param method 被代理的类的方法,即Service1中的方法
                 * @param objects 调用方法传递的参数
                 * @param methodProxy 方法代理对象
                 * @return
                 * @throws Throwable
                 */
                System.out.println("调用方法:" + method);
                //可以调用MethodProxy的invokeSuper调用被代理类的方法
                Object result = methodProxy.invokeSuper(o, objects);
                return result;
            }
        });
        //4.获取代理对象,调用enhancer.create方法获取代理对象,这个方法返回的是Object类型的,所以需要强转一下
        Service1 proxy = (Service1) enhancer.create();
        //5.调用代理对象的方法
        proxy.m1();
        proxy.m2();

        Service1 proxy1 = CglibProxy.createProxy(new Service1());
        proxy1.m2();
        proxy1.m1();
    }

通用方法

public class CglibProxy implements MethodInterceptor {

    //目标对象
    private Object target;

    public CglibProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        long starTime = System.nanoTime();
        //调用被代理对象(即target)的方法,获取结果
        Object result = method.invoke(target, objects); //@1
        long endTime = System.nanoTime();
        System.out.println(method + ",耗时(纳秒):" + (endTime - starTime));
        return result;
    }

    /**
     * 创建任意类的代理对象
     *
     * @param target
     * @param <T>
     * @return
     */
    public static <T> T createProxy(T target) {
        CglibProxy cglibProxy = new CglibProxy(target);
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(cglibProxy);
        enhancer.setSuperclass(target.getClass());
        return (T) enhancer.create();
    }
}

Service1


public class Service1 {

    public void m1() {
        System.out.println("m1");
    }

    public void m2() {
        System.out.println("m2");
    }
}