您的位置:首页 > 其它

动态代理技术

2015-02-28 23:25 375 查看
1分析代理类的作用与原理及AOP概念

当我们已经开发好了一个类,这时我们需要为这个类添加日志,计数,事务管理 那我们什么做???这时我们可以考虑使用代理。
代理模式是对象的结构型模式,代理模式给某一个对象提供了一个代理对象,并由代理对象控制对原对象的引用。


代理分为静态代理和动态代理

1.        代理分类
a)       静态代理:代理类的方法要和接口方式一致!
b)       动态代理,JDK动态代理只能对实现了接口的类进行代理,采用JDK动态代理必须实现InvocationHandler接口,采用Proxy类创建相应的代理类。
c)       动态代理的优缺点:
d)      面向接口编程方便
e)       使用的是Java反射机制 开销比较大。


2. 分析JVM通过反射生成代理类

JDK 1.5 中代理对象的生成,是通过Proxy 类生成的;
1、创建一个实例对象,先找到有参的构造方法。
2、编写一个最简单的InvotationHander
3、调用动态的方法调用动态的实例对象


代码:三种生成代理对象的方法

packageorg.nagi.proxy;
importjava.lang.reflect.Constructor;
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
/**
*三种方法生成Collection的代理对象
*@author dell
*
*/
publicclass TestProxy {

privatestaticCollectionc;
publicstaticvoid main(String[] args)throws Exception {

TestProxy.CreateProxy1();
TestProxy.CreateProxy2();
TestProxy.getProxy(c);

}

/**
*
* 第一种生成代理对象
*/
publicstaticvoid CreateProxy1()throws Exception{

//得到代理类
Class classParxy  = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
//得到其构造方法
Constructor con = classParxy.getConstructor(InvocationHandler.class);
//实现InvocationHander接口
class MyInvocationHanderimplements InvocationHandler{

public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
returnnull;
}
}
//生成了Collection的一个代理对象
Collection proxy1 = (Collection)con.newInstance(new MyInvocationHander());

}

/**
*
* 第二种生成代理对象
*/
publicstaticvoid CreateProxy2()throws Exception{

//得到代理类
Class classParxy  = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
//得到其构造方法
Constructor con = classParxy.getConstructor(InvocationHandler.class);
//生成了Collection的一个代理对象
Collection proxy1 = (Collection)con.newInstance(new InvocationHandler(){

@Override
public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
returnnull;
}

});

}
/**
*
* 第三种生成代理对象
*/
publicstatic Object getProxy(final Object target) {
Object proxy3 = Proxy.newProxyInstance(
//得到目标对象的字节码
target.getClass().getClassLoader(),
//得到目标对象所实现的接口
target.getClass().getInterfaces(),
//实现InvocationHandler接口
new InvocationHandler(){

public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
returnnull;
}
}
);
return proxy3;
}

}


2.创建动态类及查看其方法列表信息
3.创建动态类的实例对象及调用其方法
4.完成InvocationHandler对象的内部功能


public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
returnnull;
}


5.分析InvocationHandler对象的运行原理

我们在调用代理对象的时候,每一次都执行Invocation 里面Invoke方法,
而在Invoke 方法需要接收三个数据:哪一个代理对象执行,方法、参数;


5.总结分析动态代理类的设计原理与结构

思考:我们在调用代理对象的时候都要执行InvocationHander 接口里面的Invoke()方法;如果有一千个类都需要生成代理对象并且他们所需添加功能不一样 那我们什么办?


这时候我们就需要重构以一下我们的所生成的代理方法,使它可以适应为任何类添加的心新功能和生成代理对象; 我们就引出AOP 的思想;在为一个类生成代理对象的时候,我们只徐告诉它目标和需要添加的方法,为了提高可复用性和灵活性,我们把需要生成代理的类写进配置文件里面。

6.编写可生成代理和插入通告的通用方法

通知的方法:

importjava.lang.reflect.Method;
/**
*通知的借口
*即将插入进来的方法
*如:执行的时间
*   记日记  事务管理
*@author dell
*
*/
publicinterface Adrice {
publicvoid beforeClass(Method method);
publicvoid afterClass(Method method);
}
importjava.lang.reflect.Method;

/**
*实现通知方法
*@author dell
*
*/
publicclass MyAdriceimplements Adrice {
@Override
publicvoid beforeClass(Method method) {
long begain = System.currentTimeMillis();

System.out.println("start....." + begain);
}
@Override
publicvoid afterClass(Method method) {
long after = System.currentTimeMillis();

System.out.println("end....." + after);
}
}

/**
* 万能代理生成器
* @param target需要代理的对象
* @param adrice需要添加的方法
* @return 代理对象
*/
publicstatic Object CreatProxy(final Object target,final Adrice adrice){
Object proxy = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {

@Override
public Object invoke(Object proxy, Method method,Object[] args)
throws Throwable {
adrice.beforeClass(method);
Object retVal = method.invoke(target, args);
adrice.afterClass(method);
return retVal;
}
});
return proxy;
}


7.实现类似spring的可配置的AOP框架

首先AOP 存在常用接口:

BeanFactory:负责生产Bean
ProxyFactoryBean:负责生产Bean 代理对象
Adrice: 定义通知的方法接口
Config.properties : 配置为哪一个类产生代理对象


代码:

BeanFactory 工厂类
packageorg.nagi.Aop;
importjava.io.IOException;
importjava.io.InputStream;
importjava.util.Properties;
/**
* bean工厂
*@author dell
*
*/
publicclass BeanFactory {
Properties prop = new Properties();
public BeanFactory(InputStream is ) {
try {
//从输入流中加载文件
prop.load(is);
} catch (IOException e) {
e.printStackTrace();
}
}
//通过name得到Bean
public Object getBean(String name)throws Exception{
//从配置文件里面加载类
StringclassName = prop.getProperty(name);
//得到文件内存的字节码
Classclazz = Class.forName(className);
//生成一个代理对象
Objectbean = clazz.newInstance();
// 如果是代理工厂的对相的话,就加载代理目标类,和通知adrice
if(beaninstanceof ProxyFactoryBean){
//如果是代理对象,将其转为ProxyFactoryBean
ProxyFactoryBean proxyFactoryBean =(ProxyFactoryBean)bean;
//加载目标代理类
Object target = Class.forName(prop.getProperty(name +".target")).newInstance();
//加载目标的通知
AopAdvice advice = (AopAdvice) Class.forName(prop.getProperty(name +".advice")).newInstance();
//设置通知
proxyFactoryBean.setAdvice(advice);
//设置代理目标类
proxyFactoryBean.setTarget(target);
Object proxy =proxyFactoryBean.CreatProxy();
return proxy;
}
return bean;
}
}

代理工厂产生类
packageorg.nagi.Aop;
importjava.lang.reflect.InvocationHandler;
importjava.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 代理工厂
* @author dell
*
*/
public classProxyFactoryBean {

private AopAdvice advice;
private Object target;
/**
* 万能代理生成器
*@param target 需要代理的对象
*@param adrice 需要添加的方法
*@return  代理对象
*/
public Object CreatProxy(){
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.beforeClass(method);
Object retVal = method.invoke(target,args);
advice.afterClass(method);
return retVal;
}
});
return proxy;

}
public AopAdvice getAdvice() {
return advice;
}
public void setAdvice(AopAdvice advice) {
this.advice = advice;
}

public Object getTarget() {
return target;
}

public void setTarget(Object target) {
this.target = target;
}

}
通知接口类
packageorg.nagi.Aop;

importjava.lang.reflect.Method;

/**
*通知的借口
*即将插入进来的方法
*如:执行的时间
*   记日记  事务管理
*@author dell
*
*/
publicinterface BaseAdvice {

publicvoid beforeClass(Method method);
publicvoid afterClass(Method method);

}
具体通知实现类
package org.nagi.Aop;
importjava.lang.reflect.Method;
/**
*通知的具体实现类
*@author dell
*
*/
publicclass AopAdviceimplements BaseAdvice{

@Override
publicvoid beforeClass(Method method) {
long begain = System.currentTimeMillis();

System.out.println("start....." + begain);
}

@Override
publicvoid afterClass(Method method) {
long after = System.currentTimeMillis();

System.out.println("end....." + after);
}

}


配置文件:config.properties

nagi=org.nagi.Aop.ProxyFactoryBean
nagi.advice=org.nagi.Aop.AopAdvice
nagi.target=java.util.ArrayList


主函数:

packageorg.nagi.Aop;

importjava.io.InputStream;

/**
*测试类
*@author dell
*
*/
publicclass TestAop {

publicstaticvoid main(String[] args) {

InputStream is = TestAop.class.getResourceAsStream("config.properties");
BeanFactory factory = new BeanFactory(is);
try {
Object nagi = factory.getBean("nagi");
System.out.println(nagi.getClass().getName());
} catch (Exception e) {
e.printStackTrace();
}
}
}


运行结果生成一个代理对象:com.sun.proxy.$Proxy0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: