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

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

一、常规的写法

  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. Android 6.0运行时权限第三方库的使用-----RxPermissions

    运行时权限的讲解在前一篇博客已经算是说的比较清楚了,这里就不说了,如果对6.0这个新特性不是很了解的朋友建议先看看(地址:http://blog.csdn.net/qq_33923079/articl ...

  2. HTML5 Audio/Video 标签属性与事件

    chrom 只测试过部分属性,均正常,兼容性未测试: 标签属性:src:音乐的URLpreload:预加载autoplay:自动播放loop:循环播放controls:浏览器自带的控制条 1 标签属性 ...

  3. js 图片加载失败处理方法

    在项目中不可避免会用到图片,尤其是列表,有时候图片会加载失败:这样就会显示一个很难看的坏图片缩略图:下面介绍两种方法,解决这个问题: 1.如果在你的项目中有引入jQuery插件,你可以使用error( ...

  4. js的事件处理与闭包:

    var i = 0; for(i=0;i<5;i++){ (function(i){ setTimeout(function(){alert(i)},3000); })(i) } // 上面打印 ...

  5. 分享知识-快乐自己:Spring线程池配置

    Spring通过ThreadPoolTaskExecutor实现线程池技术,它是使用jdk中的Java.util.concurrent.ThreadPoolExecutor进行实现. Spring 配 ...

  6. 如何做好App的测试工作

    记得刚开始接触app测试时,可谓是一脸懵状,拿到一个功能不知道该测些什么,会因为测试范围确认不足.测试点考虑不全等导致线上问题,吃一堑才会长一智,栽过几次坑后就学会了如何避免.现总结App测试点如下, ...

  7. hdu 1907 John(anti nim)

    John Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submis ...

  8. mysql 授予远程连接直接访问

    不通过ssh通道,mysql 授予远程连接直接访问 语句 GRANT ALL PRIVILEGES ON *.* TO root@'%' IDENTIFIED BY '!DSJdg!' WITH GR ...

  9. LeetCode OJ:Subsets(子集)

    Given a set of distinct integers, nums, return all possible subsets. Note: Elements in a subset must ...

  10. tensorflow中使用tf.ConfigProto()配置Session运行参数&&GPU设备指定

    tf.ConfigProto()函数用在创建session的时候,用来对session进行参数配置: config = tf.ConfigProto(allow_soft_placement=True ...