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,即面向切面的编程.其要解决的问题就是在不改变源代码的情 ...
随机推荐
- linux查看文件被哪个进程占用?
1> 如果文件是端口号 netstat -ntlp | grep portNum [root@localhost root]# netstat -ntlp Active Internet con ...
- DEDE 首页调用指定栏目链接的代码
{dede:type typeid='6'} <a href='[field:typelink /]' target="_blank" >更多</a> {/ ...
- Spring ApplicationContext(二)环境准备
Spring ApplicationContext(二)环境准备 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) 本节介绍 ...
- Internet
0x01 URL的解析/反解析/连接 解析 urlparse()--分解URL # -*- coding: UTF-8 -*- from urlparse import urlparse url = ...
- [AI]神经网络章3 损失函数
损失函数 作用 在有监督的学习中,需要衡量神经网络输出和所预期的输出之间的差异大小.这种误差函数需要能够反映出当前网络输出和实际结果之间一种量化之后的不一致程度,也就是说函数值越大,反映出模型预测的结 ...
- Maximum Swap LT670
Given a non-negative integer, you could swap two digits at most once to get the maximum valued numbe ...
- Alpha 冲刺 (1/10)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作,对多个目标检测及文字识别模型进行评估.实验,选取较 ...
- WordCount改进 小组项目
GitHub地址:https://github.com/DM-Star/WordCount-opt 作业需求:http://www.cnblogs.com/ningjing-zhiyuan/p/865 ...
- hdu 6208(后缀自动机、或者AC自动机
题意:给你n个字符串,问你是否存在一个字符串可以从中找到其他n-1个字符串. 思路:其实很简单,找到最长的那个字符串对他进行匹配,看是否能匹配到n-1个字符串. 可以用AC自动机或者后缀自动机做,但是 ...
- my.ini优化mysql数据库性能的十个参数(推荐)
(1).max_connections:允许的同时客户的数量.增加该值增加 mysqld 要求的文件描述符的数量.这个数字应该增加,否则,你将经常看到 too many connections 错误. ...