Java 动态代理实践AOP

大家都知道Spring中AOP是通过Java动态代理实现的,今天就来简单学习下demo。

Java动态代理主要有两个核心类,InvocationHandler和Proxy。

1/** 2 * {@code InvocationHandler} is the interface implemented by 3 * the <i>invocation handler</i> of a proxy instance. 4 * 5 * <p>Each proxy instance has an associated invocation handler. 6 * When a method is invoked on a proxy instance, the method 7 * invocation is encoded and dispatched to the {@code invoke} 8 * method of its invocation handler. 9 * 10 * @author Peter Jones 11 * @see Proxy 12 * @since 1.3 13 */ 14public interface InvocationHandler

所有的Handler类要实现InvocationHandler接口,并关联到Proxy实例上,最后会分发到InvocationHandler的invoke方法上。

1/** 2 * {@code Proxy} provides static methods for creating dynamic proxy 3 * classes and instances, and it is also the superclass of all 4 * dynamic proxy classes created by those methods. 5 * 6 * <p>To create a proxy for some interface {@code Foo}: 7 * <pre> 8 * InvocationHandler handler = new MyInvocationHandler(...); 9 * Class proxyClass = Proxy.getProxyClass( 10 * Foo.class.getClassLoader(), new Class[] { Foo.class }); 11 * Foo f = (Foo) proxyClass. 12 * getConstructor(new Class[] { InvocationHandler.class }). 13 * newInstance(new Object[] { handler }); 14 * </pre> 15 * or more simply: 16 * <pre> 17 * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), 18 * new Class[] { Foo.class }, 19 * handler); 20 * </pre> 21 * 22 **************************** 23 */ 24public class Proxy implements java.io.Serializable

通过该类的静态方法创建要动态代理的类。

下面看下demo

1. 先创建一个接口

1public interface TargetInterface { 2 int targetMethod(int num); 3}

2. 实例化该接口

1public class TargetClass implements TargetInterface { 2 @Override 3 public int targetMethod(int number) { 4 System.out.println("调用目标类的方法targetMethod..."); 5 return number; 6 } 7}

3. 创建代理处理类,InvocationHandler子类

1public class ProxyHandler implements InvocationHandler { 2 Object concreteClass; 3 public ProxyHandler(Object concreteClass) { 4 this.concreteClass = concreteClass; 5 } 6 @Override 7 public Object invoke(Object proxy, Method method, Object[] args) 8 throws Throwable { 9 System.out.println("proxy:"+proxy.getClass().getName()); 10 System.out.println("method:"+method.getName()); 11 System.out.println("args:"+args[0].getClass().getName()); 12 13 System.out.println("Before invoke method..."); 14 Object object = method.invoke(concreteClass, args); 15 System.out.println("After invoke method..."); 16 return object; 17 } 18}

proxy:  指代我们所代理的那个真实对象 method: 指代的是我们所要调用真实对象的某个方法的Method对象 args:  指代的是调用真实对象某个方法时接受的参数

1public class Example { 2 public static void main(String[] args) { 3 TargetClass cc = new TargetClass(); 4 InvocationHandler ih = new ProxyHandler(cc); 5 TargetInterface tf = (TargetInterface) Proxy.newProxyInstance(cc.getClass().getClassLoader(), cc.getClass().getInterfaces(), ih); 6 7 int i = tf.targetMethod(5); 8 } 9} 10 11public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException 12 13loader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载 14interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了 15h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

注意:通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号

动态代理有个缺陷,就是创建时需要参数interfaces,即被代理的类,需要实现该接口。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Java日期时间API系列31

  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前

Spring的两种代理JDK和CGLIB的区别浅谈

一、原理区别:java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以

00:Java简单了解

浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。