Java动态代理学习【Spring AOP基础之一】

  Spring AOP使用的其中一个底层技术就是Java的动态代理技术。Java的动态代理技术主要围绕两个类进行的 

  java.lang.reflect.InvocationHandler
  java.lang.reflect.Proxy

  首先从代码层面说明Java动态代理是如何实现的,

  业务逻辑接口:

  

/**
 * 创建一个人的接口,其中有一个吃的方法
 */
public interface Person {
    public void eat();
}

  创建一个实现该业务接口的类:

/**
 * 人接口的实现,实现吃饭的方法
 */
public class PersonImpl implements Person {
    @Override
    public void eat() {
        System.out.println("吃主食、吃菜、喝汤...");
    }
}

  此时,如果正常情况如果想要调用Person这个接口,直接new它的实现类然后调用eat方法即可,但是如果想要实现一个Person的代理,并且在eat方法前后进行一些工作就需要使用Proxy和InvovationHandler;

  InvocationHandler接口的实现类,(代理类中额外逻辑的实现就需要在这里进行)

/**
 * 代理类的额外逻辑实现类
 */
public class InvocationHandlerImpl implements InvocationHandler {
    Person person;
    public InvocationHandlerImpl(Person person) {
        this.person = person;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if(method.getName().equalsIgnoreCase("eat")) {
            System.out.println("洗手...");
            method.invoke(person, args);
            System.out.println("刷牙");
        }
        return person;
    }
}

  

  接下来就是使用Proxy生成代理类,Proxy需要业务逻辑接口,代理类额外实现逻辑InvocationHandler实现类

/**
 * 代理类产生并且测试
 */
public class ProxyGenerate {
    @Test
    public void proxyTest() {
        Person person = new PersonImpl();
        InvocationHandler invocationHandler = new InvocationHandlerImpl(person);
        Person personProxy = (Person)Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, invocationHandler);
        personProxy.eat();
    }

}

  

  输出内容如下:

  代理类已经成功的完成代理。

  AOP的功能就是在一个方法前、后、异常抛出等地方添加逻辑,与上面的过程是一样的,所以这个技术就被用来实现Spring AOP的一个技术,但是这个只针对接口实现,如果想要给一个类添加AOP的逻辑,这个Proxy动态代理的技术暂时无法适用,Spring AOP适用了CGLIB,支持类的动态代理,但是不属于这一次的讨论范畴。

  知道怎么用了之后是不是对Proxy这个感觉很神奇,想知道是如何实现的呢,可以深入了解一下newProxyInstance这个方法:

  

  找到上述内容,可以看到这个是动态生成代理类字节数组的方法,所以我们可以通过这个方法了解到动态生成的代理类的结构:

/**
 * 代理类产生并且测试
 */
public class ProxyGenerate {
    @Test
    public void proxyWatch() {
        byte[] classByte = ProxyGenerator.generateProxyClass("PersonDynamicProxy", new Class[]{Person.class});
        try {
            FileOutputStream var1 = new FileOutputStream("PersonDynamicProxy" + ".class");
            var1.write(classByte);
            var1.close();
        } catch (IOException var2) {
            throw new InternalError("I/O exception saving generated file: " + var2);
        }
    }
}

  执行上述代码会生成动态代理对象的.class文件

  反编译(jd-gui,idea)之后就可以看到动态代理类的结构:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import com.smart.beanfactory.Person;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class PersonDynamicProxy extends Proxy implements Person {
    private static Method m1;
    private static Method m3;
    private static Method m0;
    private static Method m2;

    public PersonDynamicProxy(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void eat() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m3 = Class.forName("com.smart.beanfactory.Person").getMethod("eat", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

  可以看出来,动态代理类首先通过反射的技术,将源接口中的方法均设置为其静态属性(Method),然后针对每个方法进行重写。

  重写的逻辑是使用invocationHandler接口的invoke方法实现,每个invoke方法在绑定相应的反射出来的静态属性即可。

  举例,比如上面Person接口的eat被反射未m3的静态属性中,重写eat()方法是调用方法为invoke(this, m3, args),其中invoke中会有额外添加的一些逻辑,

时间: 2024-08-10 02:09:06

Java动态代理学习【Spring AOP基础之一】的相关文章

java动态代理学习笔记

没事的时候翻看lang.reflect包下的代码,发现有两部分内容:涉及反射和动态代理. 很多地方都可以看到动态代理的影子,只是一直没仔细看下. 在学习之前,先提出几个问题,带着问题来看代码: 1.什么是动态代理? 2.为什么使用动态代理? 3.使用它有哪些好处? 4.哪些地方需要动态代理? --------------------分隔线----------------------------- 和动态代理有关的有两个类 1.interface InvocationHandler Object

Java动态代理学习

动态代理类 Java动态代理类位于java.lang.reflect包下,一般主要涉及到以下两个类: 1.Interface InvocationHandler 该接口中仅定义了一个方法: Object invoke(Object proxy, Method method, Object[] args) 在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,如上例中的request(),args为该方法的参数数组(无参时设置为null). 这个抽象方法在代理类中动态实现. 2

JAVA 动态代理学习记录

打算用JAVA实现一个简单的RPC框架,看完RPC参考代码之后,感觉RPC的实现主要用到了两个方面的JAVA知识:网络通信和动态代理.因此,先补补动态代理的知识.---多看看代码中写的注释 参考:Java 代理模式与动态代理类 java的动态代理机制详解 在动态代理中,首先定义一个接口,这个接口中声明的方法 是 真实类需要实现的,真实类实现该方法来提供具体的操作. public interface Subject { public abstract void request(); } publi

从动态代理到Spring AOP(上)

一.前言 虽然平时日常开发很少用到动态代理,但是动态代理在底层框架等有着非常重要的意义.比如Spring AOP使用cglib和JDK动态代理,Hibernate底层使用了javassit和cglib动态代理,Dubbo使用javassist字节码(具体可以看Dubbo SPI). 本文主要介绍什么是动态代理及原理,下文将介绍Spring AOP 我们先思考一个问题:如何统计一个类各个方法的执行时间?可能你心里有好多答案都可以解决问题. 那么如果是这个项目的多个不同类呢?可能心里也有答案,但是代

java动态代理与老式AOP实现

JAVA的动态代理 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,代理类可以分为两种. class文件就已经存在了. 动态代理:在程序运行时,运用反射机制动态创建而成. 首先看一下静态代理: /** *

【设计模式】代理模式:静态代理,动态代理,spring aop

代理模式分为静态代理和动态代理.我们拿链家来举例子,我们本人是真实的对象,有真实的业务需求:需要去找房子:链家是中介,是代理类,他来帮我执行找房子的这个操作. 静态代理: 1.实现一个接口 public interface SearchHome { public void search(); } 2.构建实现接口的委托类 public class Master implements SearchHome { @Override public void search() { System.out.

java 动态代理学习(Proxy,InvocationHandler)

前几天看到java的动态代理机制,不知道是啥玩意,然后看了看.死活不知道 invoke(Object proxy, Method m, Object[] args)种的proxy是个什么东西,放在这里有什么用?于是网上到处搜刮,把自己的理解写了写. /** * 相亲接口 * * @author zhengt * @time Jun 3, 2095 3:13:03 PM */ public interface XiangQinInterface { /** * 相亲方法 */ public voi

反射实现AOP动态代理模式(Spring AOP实现原理)

其实AOP的意思就是面向切面编程. OO注重的是我们解决问题的方法(封装成Method),而AOP注重的是许多解决问题的方法中的共同点,是对OO思想的一种补充! 还是拿人家经常举的一个例子讲解一下吧: 比如说,我们现在要开发的一个应用里面有很多的业务方法,但是,我们现在要对这个方法的执行做全面监控,或部分监控.也许我们就会在要一些方法前去加上一条日志记录. 我们写个例子看看我们最简单的解决方案 我们先写一个接口IHello.java代码如下: package sinosoft.dj.aop.st

动态代理实现Spring Aop

引言 我们在前两篇文章中,都为这篇做了铺垫,我们现在来做这样一件事情,在业务逻辑中添加Aop的非业务逻辑. AopClinetTest: package com.tgb.client; import com.tgb.config.BeanFactory; import com.tgb.config.ClassPathXmlApplicationContext; import com.tgb.dao.UserDao; import com.tgb.domain.User; /** * AOP效果测