动态代理技术就是用来产生一个目标对象的代理对象的,代理对象应与目标对象(被代理的对象)有相同的方法,实现对目标对象访问的拦截,并增强目标对象的一些功能,而不需要目标对象去做任何的更改,使得目标对象有更加纯粹的业务逻辑。不多解释,上代码。

  需求:在一个业务模块方法中添加日志。

一、常规的写法

  1.1、接口Animals

package com.duchong.proxy_test;

/**
* @author DUCHONG
* @since 2017-12-28 9:10
**/
public interface Animals {
/**
* 吃
* @param name
* @return
*/
String eat(String name); /**
* 吠
* @param name
* @return
*/
String bark(String name); /**
* 跑
* @param name
* @return
*/
String move(String name);
}

  1.2、接口的实现类Dog

package com.duchong.proxy_test;

/**
* @author DUCHONG
* @since 2017-12-28 9:21
**/
public class Dog implements Animals { @Override
public String eat(String name) {
System.out.println("Dog eat method start.....");
return "dog eat "+name;
} @Override
public String move(String name) {
System.out.println("Dog move method start.....");
return "dog move "+name;
} @Override
public String bark(String name) {
System.out.println("Dog bark method start.....");
return "dog bark "+name;
} public static void main(String[] args) {
Dog dog=new Dog();
System.out.println(dog.eat("Bone"));
System.out.println(dog.move("Faster"));
System.out.println(dog.bark("Wang Wang Wang"));
}
}

  1.3、输出

以上写法,能实现要求,但是缺点是,像日志这种非业务逻辑相关的代码混在里面,看起来混乱,不易维护,而且这些代码块大多类似,对于这样的代码块,我们都知道,是可以抽取出来的,定义公共功能,这样就使得业务模块更简洁, 只包含核心业务代码。

二、基于动态代理的写法

2.1、接口的实现类Dog

package com.duchong.proxy_test;

/**
* @author DUCHONG
* @since 2017-12-28 9:21
**/
public class Dog implements Animals {
@Override
public String eat(String name) {
return "dog eat "+name;
} @Override
public String move(String name) {
return "dog move "+name;
} @Override
public String bark(String name) {
return "dog bark "+name;
} }

2.2、使用java.lang.reflect.Proxy动态代理实现,即提取目标对象的接口(或者说JDK生成代理必须使用接口),然后对接口创建代理.

@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException

使用Proxy.newProxyInstance方法就可以返回一个代理对象,这个方法总共有3个参数

  • ClassLoader loader 生成代理对象使用哪个类装载器加载
  • Class<?>[] interfaces 生成哪个对象的代理对象,通过接口指定,或者说代理要实现的接口
  • InvocationHandler h 产生的这个代理对象要做什么,这个接口里面只有一个方法,可以使用一个匿名内部类来实现

2.3、代理类

package com.duchong.proxy_test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* dog代理类
*
* @author DUCHONG
* @since 2017-12-28 10:17
**/
public class DogProxy{ //需要被代理的目标对象
private Animals target; public DogProxy(Animals target){
this.target=target;
} /**
* 返回基于接口创建的代理
* @return
*/
public Animals getDogProxy(){ return (Animals) Proxy.newProxyInstance(DogProxy.class.getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if(method.getName().equals("eat")){
System.out.println("Dog eat method start.....");
return method.invoke(target,args);
}
else if(method.getName().equals("move")){
System.out.println("Dog move method start.....");
return method.invoke(target,args);
}
else if(method.getName().equals("bark")){
System.out.println("Dog bark method start.....");
return method.invoke(target,args);
}
else{
return null;
}
}
}); } }

2.4、Main运行

package com.duchong.proxy_test;
/**
* @author DUCHONG
* @since 2017-12-28 10:35
**/
public class Main {
public static void main(String[] args) {
//目标对象
Animals animals=new Dog();
//获得代理对象
Animals dog= new DogProxy(animals).getDogProxy();
//调用代理对象的方法
System.out.println(dog.eat("Bone"));
System.out.println(dog.move("Faster"));
System.out.println(dog.bark("Wang Wang Wang"));
}
}

2.5、输出

2.6、InvocationHandler原理

  如果Proxy生成代理对象的时候,指定了InvocationHandler,那么用户调用代理对象的任何方法,该方法都是调用InvocationHandler的invoke方法,而Method就是当前调用的那个方法,通过getName 即可获取当前被调用方法的名称,从而在invoke被调用之前,添加日志等处理,而invoke方法被调用是需要两个参数,一个是调用改方法的对象,一个是该方法的参数,即为代码中的target和args.

AOP基础-JDK动态代理的更多相关文章

  1. Java基础-jdk动态代理与cglib动态代理区别

    JDK动态代理 此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前后加上其他业务处理逻辑. 代理模式在实际使用时需要指定具体的目标对象 ...

  2. spring---aop(2)---Spring AOP的JDK动态代理

    写在前面 spring 事务是springAOP 的一个实现.我们以分析spring的事务,来分析spring的AOP实现. 基本知识 如果目标方法被spring的事务声明,则执行该目标方法的对象就会 ...

  3. Java基础-JDK动态代理

    JDK的动态代理依靠接口实现  代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代 ...

  4. (转)细说JDK动态代理的实现原理

    原文:http://blog.csdn.net/mhmyqn/article/details/48474815 关于JDK的动态代理,最为人熟知的可能要数Spring AOP的实现,默认情况下,Spr ...

  5. spring---aop(4)---Spring AOP的CGLIB动态代理

    写在前面 前面介绍了Spring AOP的JDK动态代理的过程,这一篇文章就要介绍下Spring AOP的Cglib代理过程. CGLib全称为Code Generation Library,是一个强 ...

  6. Spring Boot实践——Spring AOP实现之动态代理

    Spring AOP 介绍 AOP的介绍可以查看 Spring Boot实践——AOP实现 与AspectJ的静态代理不同,Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改 ...

  7. AOP-底层原理(JDK动态代理实现)

    AOP(JDK动态代理) 1,使用JDK动态代理,使用Proxy类里面的方法创建代理对象 (1)调用 newProxyInstance 方法 方法有三个参数 第一参数,类加载器 第二参数,增强方法所在 ...

  8. 【spring基础】AOP概念与动态代理详解

    一.代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为”代理“,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一 ...

  9. AOP的底层实现-CGLIB动态代理和JDK动态代理

    AOP是目前Spring框架中的核心之一,在应用中具有非常重要的作用,也是Spring其他组件的基础.它是一种面向切面编程的思想.关于AOP的基础知识,相信多数童鞋都已经了如指掌,我们就略过这部分,来 ...

随机推荐

  1. 红米1S.线刷

    ZC:遇到问题:“Missmatching image and device”,解决网址:“[2.23][史上最全]MiFlash线刷错误的那些事儿_收藏备用_小米手机4_MIUI论坛.html”(h ...

  2. js适配器模式

    适配器模式,将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范 ...

  3. tensorflow1.0中的改善

    TensorFlow 1.0 重大功能及改善 XLA(实验版):初始版本的XLA,针对TensorFlow图(graph)的专用编译器,面向CPU和GPU. TensorFlow Debugger(t ...

  4. [thinkphp使用phpspreadsheet时出现]Cannot redeclare xxxxxx() (previously declared in C:\WWW\xxx.xxx:xxx)

    [thinkphp使用phpspreadsheet时出现]Cannot redeclare xxxxxx() (previously declared in C:\WWW\xxx.xxx:xxx) 一 ...

  5. 缓存淘汰算法--LRU算法(转)

    (转自:http://flychao88.iteye.com/blog/1977653) 1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访 ...

  6. Ubuntu下使用tmux实现分屏,以及tmux快捷键

    最近用到了终端的复用,使用了tmux,写一下自己的使用和一些快捷键. tmux是指通过一个终端登录远程主机并运行后,在其中可以开启多个控制台的终端复用软件. 来个效果图: 截图我使用的命令是  gno ...

  7. [Unity3D]EZGUI 操作简单介绍

    官方的GUI根本无法跟EZGUI比,无论是资源还是易用性还是速度.EZGUI基于Mesh不占DrawCall.EZGUI是自动合并Mesh成为一个物体,并且贴图自动制作Atlas.所以效率高,CPU消 ...

  8. 转载:关于消息队列的使用----ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ

    转载: http://blog.csdn.net/konglongaa/article/details/52208273

  9. [转] AS3地图拼接与战争迷雾的实现

    在开发游戏的过程中,特别是地图编辑器中,需要利用最少的资源,实现最丰富的地形地貌.虽然现在众多的RPG开始使用整图,但是我们偶尔还是需要能够让玩家自己编辑地图,或者其他需要自动进行地图构建的功能.另外 ...

  10. 【转】JVM虚拟性能分析

    JDK自带的JAVA性能分析工具.它已经在你的JDK bin目录里了,只要你使用的是JDK1.6 Update7之后的版本.点击一下jvisualvm.exe图标它就可以运行了. 这里是VisualV ...