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

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

一、常规的写法

  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. Redis缓存集群方案

    由于单台Redis服务器的内存管理能力有限,使用过大内存的Redis又会使得服务器的性能急剧下降,一旦服务器发生故障将会影响更大范围业务,而Redis 3.0 beta1支持的集群功能还不适合生产环境 ...

  2. jmeter-察看结果树-响应数据,中文显示乱码问题处理

    第一步: 打开路径:jmeter\bin\jmeter.properties 文件 第二步: 文件中默认编码为:ISO-8859-1 修改为utf-8 sampleresult.default.enc ...

  3. Maven知识点简要

      1.依赖管理 <dependencies> <dependency> <groupId>net.sf.json-lib</groupId> < ...

  4. 【WCF】利用WCF实现上传下载文件服务

    引言     前段时间,用WCF做了一个小项目,其中涉及到文件的上传下载.出于复习巩固的目的,今天简单梳理了一下,整理出来,下面展示如何一步步实现一个上传下载的WCF服务. 服务端 1.首先新建一个名 ...

  5. JSP学习笔记(九十):eclipse3.4中建立控制台程序

    1.控制台程序的建立 File->New->Application Client Project,勾选上Create a default Main class 找到Main.java,修改 ...

  6. Android Design TextinputLayout

    使用该布局 需要在build.gradle中的dependencies块中添加两个依赖来向下兼容 dependencies { compile fileTree(dir: 'libs', includ ...

  7. (转)Android 弹软键盘时listview的变化控制

    本文转自于:http://blog.csdn.net/hellohaifei/article/details/9377483 问题描述:界面中有三部分,上面是标题栏,中间是Listview,下面是输入 ...

  8. Git_学习_09_指定某些文件不上传

    一.前言 在git提交文件到远程分支时,可能有些文件我们并不想上传. 这时可以使用如下命令来将这些文件从暂存区移除 git rm --cached "文件路径" 注:git add ...

  9. Git学习--创建版本库

    什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改.删除,Git都能跟踪,以便任何时刻都可以追踪历史,或 ...

  10. BEC translation exercise 7

    在挑选时我们完全出自疏忽而漏过了这篇短文.In making the selection we passed this short piece by quite inadvertently. we l ...