代理模式 
        代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

按照代理的创建时期,代理类可以分为两种:
静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。
动态代理:在程序运行时,运用反射机制动态创建而成。

在JDK 1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例。 JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler是一个接口,可以通过实现该接口定义横切逻辑,在并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编织在一起。

一、静态代理
1. 接口类:Count.java

public interface Count {
// 查看账户方法
public void queryCount();
// 修改账户方法
public void updateCount();
}

2. 实现类:CountImpl.java

public class CountImpl implements Count {
@Override
public void queryCount() {
System.out.println("查看账户方法...");
} @Override
public void updateCount() {
System.out.println("修改账户方法...");
}
}

3. 代理类:CountProxy.java

public class CountProxy implements Count {
private CountImpl countImpl; /**
* 覆盖默认构造器
* @param countImpl
*/
public CountProxy(CountImpl countImpl) {
this.countImpl = countImpl;
} @Override
public void queryCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.queryCount();
System.out.println("事务处理之后");
} @Override
public void updateCount() {
System.out.println("事务处理之前");
// 调用委托类的方法;
countImpl.updateCount();
System.out.println("事务处理之后");
}
}

4. 测试类:TestCount.java

public class TestCount {
public static void main(String[] args) {
CountImpl countImpl = new CountImpl();
CountProxy countProxy = new CountProxy(countImpl);
countProxy.updateCount();
countProxy.queryCount();
}
}

观察代码可以发现每一个代理类只能为一个接口服务,这样一来程序开发中必然会产生过多的代理,而且,所有的代理操作除了调用的方法不一样之外,其他的操作都一样,则此时肯定是重复代码。解决这一问题最好的做法是可以通过一个代理类完成全部的代理功能,那么此时就必须使用动态代理完成。

二、动态代理

1. 接口类:

public interface PersonService {

    public String getPersonName(Integer personId);

    public void save(String name);

    public void update(Integer personId, String name);
}

2. 实现类:

public class PersonServiceBean implements PersonService {

    public String user = null;

    public PersonServiceBean(){};

    public PersonServiceBean(String user){
this.user = user;
} @Override
public String getPersonName(Integer personId) {
System.out.println("这是find方法"); return this.user;
} @Override
public void save(String name) {
System.out.println("这是save方法");
} @Override
public void update(Integer personId, String name) {
System.out.println("这是update方法");
} public String getUser() {
return user;
} public void setUser(String user) {
this.user = user;
}
}

3. JDK动态代理代理类:

/**
* 切面
*/
public class JDKProxyFactory implements InvocationHandler { private Object proxyObject; //目标对象 /**
* 绑定委托对象并返回一个代理类
* @param proxyObject
* @return
*/
public Object createProxyInstance(Object proxyObject) {
this.proxyObject = proxyObject;
//生成代理类的字节码加载器
ClassLoader classLoader = proxyObject.getClass().getClassLoader();
//需要代理的接口,被代理类实现的多个接口都必须在这里定义 (这是一个缺陷,cglib弥补了这一缺陷)
Class<?>[] proxyInterface = proxyObject.getClass().getInterfaces();
//织入器,织入代码并生成代理类
return Proxy.newProxyInstance(classLoader, proxyInterface, this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
PersonServiceBean bean = (PersonServiceBean)this.proxyObject;
Object result = null;
//控制哪些用户执行切入逻辑
if(bean.getUser() != null) {
//执行原有逻辑
result = method.invoke(this.proxyObject, args);
} return result;
}
}

4. 测试类:

public class AopTest {
@Test
public void proxyTest() {
JDKProxyFactory jpf = new JDKProxyFactory();
PersonServiceBean personService = (PersonServiceBean) jpf.createProxyInstance(new PersonServiceBean("XXX"));
personService.save("888");
}
}

上面是提供了用户名的,所以终端会打印出”我是save()方法“,然后我们将 Java代码

PersonServiceBean personService = (PersonServiceBean)jpf.createProxyInstance(new PersonServiceBean("XXX"));  
改为不提供用户名,即
PersonServiceBean personService = (PersonServiceBean) jpf.createProxyInstance(new PersonServiceBean());  

这时候在允许代码发现终端不打印出"我是save()方法",证明我们的动态代理是成功的。

[转]JDK动态代理的更多相关文章

  1. JDK动态代理

    一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...

  2. 静态代理和利用反射形成的动态代理(JDK动态代理)

    代理模式 代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 静态代理 1.新建 ...

  3. Spring中的JDK动态代理

    Spring中的JDK动态代理 在JDK1.3以后提供了动态代理的技术,允许开发者在运行期创建接口的代理实例.在Sun刚推出动态代理时,还很难想象它有多大的实际用途,现在动态代理是实现AOP的绝好底层 ...

  4. AOP学习心得&jdk动态代理与cglib比较

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善.OOP引入 ...

  5. JDK动态代理的实现原理

    学习JDK动态代理,从源码层次来理解其实现原理参考:http://blog.csdn.net/jiankunking/article/details/52143504

  6. Java中的JDK动态代理

    所谓代理,其实就是相当于一个中间人,当客户端需要服务端的服务时,不是客户直接去找服务,而是客户先去找代理,告诉代理需要什么服务,然后代理再去服务端找服务,最后将结果返回给客户. 在日常生活中,就拿买火 ...

  7. JDK动态代理与CGLib动态代理

    1.JDK动态代理 JDK1.3以后java提供了动态代理技术,允许开发者在运行期创建接口的代理实例,动态代理是实现AOP的绝好底层技术. JDK的动态代理主要涉及到java.lang.reflect ...

  8. jdk动态代理实现

    1.jdk动态代理的简单实现类 package com.proxy; import java.lang.reflect.InvocationHandler; import java.lang.refl ...

  9. java jdk动态代理

    在面试的时候面试题里有一道jdk的动态代理是原理,并给一个事例直接写代码出来,现在再整理一下 jdk动态代理主要是想动态在代码中增加一些功能,不影响现有代码,实现动态代理需要做如下几个操作 1.首先必 ...

  10. JDK动态代理的实现及原理

    Proxy.newProxyInstance(classloader,Class,invocationHandler) 调用getProxyClass0(loader, interfaces)生成代理 ...

随机推荐

  1. SharePoint REST API - 文件夹和文件

    博客地址:http://blog.csdn.net/FoxDave 本篇讲述如何通过REST操作文件夹和文件. 使用REST操作文件夹 在你知道某个文档库中的文件夹的URL时,可以使用如下的代码获 ...

  2. TensorFlow随机值:tf.random_normal函数

    tf.random_normal 函数 random_normal( shape, mean=0.0, stddev=1.0, dtype=tf.float32, seed=None, name=No ...

  3. Python爬虫框架Scrapy实例(三)数据存储到MongoDB

    Python爬虫框架Scrapy实例(三)数据存储到MongoDB任务目标:爬取豆瓣电影top250,将数据存储到MongoDB中. items.py文件复制代码# -*- coding: utf-8 ...

  4. vue--http请求的封装--session

    export function Fecth (url, data, file, _method) { if (file) { // 需要上传文件 return new Promise((resolve ...

  5. 【Python】多线程-2

    1.    进程和线程的区别: (1) 一个进程可以有多个线程,一个进程中的多个线程共享该进程的所有资源,多线程切换比多进程切换快,因为不用上下文切换,Python中并发建议用多进程 (2) 进程是资 ...

  6. angular上传获取图片的directive指令

    在AngularJS中,操作DOM一般在指令中完成,那么指令是如何实现的呢?指令的作用是把我们自定义的语义化标签替换成浏览器能够认识的HTML标签 一般的事件监听是在对静态的dom绑定事件,而如果在指 ...

  7. 计时器---JS

    <script type="text/javascript"> function count(){ var a=document.getElementById(&quo ...

  8. 强化学习基础算法入门 【PPT】

    该部分内容来自于定期的小组讨论,源于师弟的汇报. ==============================================

  9. 无重复字符的最长子串-LeetCode-第3题-C++

    题目:无重复字符的最长子串 题目描述:给定一个字符串,找出不含有重复字符的最长子串的长度. 最长不重复子串可能有很多个,但是其长度只有一种. 方法一:暴力搜索法 方法二:滑动窗口 哈希表:要查找一个元 ...

  10. jQuery.Deferred exception: $.get is not a function TypeError: $.get is not a function

    /********************************************************************** * jQuery.Deferred exception: ...