Java-动态代理技术
1.程序中的代理
为具有相同接口的目标类的各个方法,添加一些系统功能,如日志,异常处理,计算方法运行的
时间,事务管理等等,都可以交给另一个类去实现这些功能,该类称为代理类。
注意:为了让代理类共享目标类中的各个方法,可以让代理类实现和目标类相同的接口。

public class AProxy {
//AProxy类为A的代理类,可以计算sayHi方法的运行时间
public void getTime()
{
//方法开始前时间
new A().sayHi();
//方法结束后时间
}
}
class A
{
void sayHi()
{
System.out.println("hi,everyone!");
}
}

2.代理架构图

它采用工厂模式和配置文件的方式进行管理,这样就不需要修改客户端程序,通过
配置文件指定使用目标类,还是代理类。这样做添加/去掉系统功能变得简单。
当我们需要测试系统的性能时,可以使用代理类,客户要使用时可以使用目标类
3.AOP(Aspect oriented program)
交叉业务:要处理不同层面的业务(service),称为交叉业务,如安全,事务,日志等。
安全 事务 日志
StudentService ------|----------|------------|-------------
CourseService ------|----------|------------|-------------
MiscService ------|----------|------------|-------------
用具体的程序代码描述交叉业务:
method1 method2 method3
{ { {
------------------------------------------------------切面
.... .... ......
------------------------------------------------------切面
} } }
面向方面的编程(简称AOP),AOP的目标就是要使交叉业务模块化。
可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的,如下所示:
------------------------------------------------------切面
func1 func2 func3
{ { {
.... .... ......
} } }
------------------------------------------------------切面
这里就是使用代理技术解决这种问题,代理是实现AOP功能的核心和关键技术。
4.动态代理技术
- 要为系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,将是一件非常麻烦的事情!
- JVM提供了动态代理类(Proxy)。即可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类。这里是仅指具有接口的代理类和目标类。
- 对于没有接口的目标类,CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
代理方法中的有如下四个位置加上系统功能代码:
1.在调用目标方法之前
2.在调用目标方法之后
3.在调用目标方法前后
4.在处理目标方法异常的catch块中

class proxy{
void sayHello(){
………//1
try{
target.sayHello();
}catch(Exception e){
………//4
}
…………//2
}
}

5.Proxy(代理类)
|-java.lang.reflect.Proxy
Proxy提供了创建动态代理类和实例的静态方法,它也是这些创建出来类的超(父)类。
构造方法:
protected Proxy(InvocationHandler h);//使用其调用处理程序的指定值从子类(通常为动态代理类)构建新的 Proxy 实例
成员方法:
static Class<?> getProxyClass(ClassLoader loader,Class<?> interfaces);//创建一个具有接口的动态代理类。
static Object newProxyInstance (ClassLoader loader,Class<?>[] interfaces,InvocationHandler h);//返回一个代理类实例对象
创建代理类及其实例对象:
法一:先创建代理类,再用代理类的构造方法创建实例对象

public static void main(String[] args) {
// 获得一个集合接口的代理类,为其指定接口和类加载器
//通常loader,interface是一样的字节码产生的
Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzProxy1.getName());
//创建一个代理类实例
//注意:clazzProxy1.newInstance()调用的是它的无参构造方法创建实例,但是它没有无参的构造方法
//通过有参构造方法创建实例
Constructor ct=clazzProxy1.getConstructor(InvocationHandler.class);
class MyinvocationHandler implements InvocationHandler
{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return null;
}
}
Collection proxy1=(Collection) ct.newInstance(new MyinvocationHandler());
}}

法二:用new方法直接创建代理类实例对象

Object target=new Object ();
Object proxy1=Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler(){ @Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
}); Class<?> []cs={Collection.class};
Collection proxy3=(Collection)Proxy.newProxyInstance
(Collection.class.getClassLoader(),
cs,new MyinvocationHandler());
Collection proxy4=(Collection)Proxy.newProxyInstance
(Collection.class.getClassLoader(),
new Class[] {Collection.class},
new MyinvocationHandler());

6.InvocationHandler(接口)
成员方法:
Object invoke(Object proxy, Method method, Object[] args);//在代理实例上处理方法调用并返回结果。
事实上,Proxy代理类对象调用(该接口上的)方法时,其实是去调用了handler的
invoke方法。对于不是该接口上的方法,如getClass(),则调用它本身的,不用委托handler去调用invoke方法。

7.代理类的模式
以面向对象的思想处理AOP(面向方面编程)的业务,即在实现代理的系统功能时,将目标类对象和接口(该接口通常以实现接口某个类的方式传入,实现接口里的方法(系统功能)的类)作为参数传入一个要实现系统功能的方法中。

ArrayList al=new ArrayList();
Collection proxy4=(Collection)getProxy(al,new Myadvice());
proxy4.add("hq");
//以下是封装了实现代理功能的一个方法
//参数:目标类对象,和接口(实现代理功能的类,类里有实现功能的方法),该接口通常以实现接口某个类的方式传入。
private static Object getProxy(final Object target,final interfaceAdvice advice) {
Object proxy=Proxy.newProxyInstance
(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler(){ @Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
advice.beforeMethod(method);
Object obj=method.invoke(target, args);
advice.afterMethod(method);
return obj;
}
});
return proxy;
}

8.实现AOP功能的封装与配置
工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例 对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的 getProxy方法返回的对象。
BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:
#xxx=java.util.ArrayList
xxx=cn.itcast.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=cn.itcast.MyAdvice
ProxyFacotryBean充当封装生成动态代理的工厂,需要为工厂类提供哪些配置参数信息?
目标:target
通知:advice
编写客户端应用:
编写实现Advice接口的类和在配置文件中进行配置
调用BeanFactory获取对象。
摘自:
http://www.cnblogs.com/beyondbycyx/p/4314536.html
Java-动态代理技术的更多相关文章
- java动态代理技术
主要用来做方法的增强.让你能够在不改动源代码的情况下,增强一些方法,在方法运行前后做不论什么你想做的事情(甚至根本不去运行这种方法).由于在InvocationHandler的invoke方法中,你能 ...
- 代理模式 & Java原生动态代理技术 & CGLib动态代理技术
第一部分.代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常 ...
- Java中动态代理技术生成的类与原始类的区别 (转)
用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...
- Java中动态代理技术生成的类与原始类的区别
用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...
- Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架
类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...
- Java中动态代理技术生成的类与原始类的区别 (good)
用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后 ...
- java动态代理原理
我们经常会用到Java的动态代理技术, 虽然会使用, 但是自己对其中的原理却不是很了解.比如代理对象是如何产生的, InvocationHandler的invoke方法是如何调用的?今天就来深究下Ja ...
- 【转载】Java 动态代理
Java 动态代理 本文为 Android 开源项目源码解析 公共技术点中的 动态代理 部分项目地址:Jave Proxy,分析的版本:openjdk 1.6,Demo 地址:Proxy Demo分析 ...
- Java动态代理简单应用
概念 代理模式是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象.这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色. Java动态代理比 ...
- Spring AOP 和 动态代理技术
AOP 是什么东西 首先来说 AOP 并不是 Spring 框架的核心技术之一,AOP 全称 Aspect Orient Programming,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...
随机推荐
- BZOJ1059或洛谷1129 [ZJOI2007]矩阵游戏
BZOJ原题链接 洛谷原题链接 通过手算几组例子后,很容易发现,同一列的\(1\)永远在这一列,且这些\(1\)有且仅有一个能产生贡献,行同理. 所以我们可以只考虑交换列,使得每一行都能匹配一个\(1 ...
- python提取百度经验<标题,发布时间,平均流量,总流量,具体的链接>
之前想研究下怎么抓网页数据.然后就有了下面的练习了. 如有BUG.也纯属正常. 只是练习.请勿投入产品使用. #!/usr/bin/python # -*- coding: utf-8 -*- #Fi ...
- mysql5.6改进子查询实测试
表t1,t2 各自生成100万条记录. 表引擎 myiasm ,查询语句 select * from t1 where id2 in (select id2 from t2 ) 查询速度 2.x秒 ...
- Delphi、Lazarus保留字、关键字详解
Delphi.Lazarus保留字.关键字详解 来自橙子,万一的博客以及其他地方 保留字:变量等标识符可以再使用: 关键字:有特定含义,不能再次重新定义: 修饰字:类似保留字的功能,也就是说可以重用 ...
- Java 使用 jacob 将 word 文档转换为 pdf 文件
网上查询了许许多多的博客,说利用 poi.iText.Jsoup.jdoctopdf.使用 jodconverter 来调用 openOffice 的服务来转换等等,我尝试了很多种,但要么显示不完全, ...
- openssl RSA基本加密解密
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <openssl/bn ...
- Spring Boot学习笔记:kafka应用
Kafka作为众多Java消息中间件之一,有诸多优点.本文讲解Kafka的应用.学习一个新的知识点,建议先找一个demo,越简单越好的demo,跑通这个demo,了解大致原理,然后在分析细节,详细了解 ...
- WPF禁止拖拽窗口到边缘自动最大化
近期有个需求,可以通过拖拽改变窗口大小,但是不允许窗口最大化.最小化.拖到边缘的时候也不能自动最大化. 要想禁止拖拽窗口到边缘自动最大化,只要改注册表即可,但是系统所有应用都会被禁止. 1.运行reg ...
- python之Flask框架
一.简单的Flask框架 1)flask简介 Flask 是一个 web 框架.也就是说 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序. 这个 wdb 应用程序可以使一些 we ...
- 取消IDEA中代码重复的检测