您的位置:首页 > 运维架构

让动态生成的类成为目标类的代理-实现AOP功能的封装与配置

2011-02-11 14:14 483 查看
让动态生成的类成为目标类的代理
·分析动态代理的工作原理图



·怎样将目标类传递进去?
-直接在InvocationHandler实现类中创建目标类的实例对象,可以看运行效果和加入日志代码,但没有实际意义。
-为InvocationHandler实现类注入目标类的实例对象,不能采用匿名内部类的形式了。
-让匿名的InvocationHandler实现类访问外面方法中的目标类实例对象的final类型的引用变量。
·将创建代理的过程改为一种更优雅的方式,eclipse重构出一个getProxy方法绑定接收目标同时返回代理对象,让调用者更懒惰,更方便,调用者甚至不用接触任何代理的API。
·将系统功能代码模块化,即将切面代码也改为通过参数形式提供,怎样把要执行的系统功能代码以参数形式提供?
-把要执行的代码装到一个对象的某个方法里,然后把这个对象作为参数传递,接收者只要调用这个对象的方法,即等于执行类外界 提供的代码!
-为bind方法增加Advice参数。
以上编程代码:
package lqq.heima.day3;

import java.lang.reflect.Method;

public interface Advice {

void beforeMethod(Method method);
void afterMethod(Method method);

}
package lqq.heima.day3;

import java.lang.reflect.Method;

public class MyAdvice implements Advice {

long beginTime = 0;
@Override
public void afterMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("张孝祥Java高新技术学习完成了");
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");

}

@Override
public void beforeMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("张孝祥Java高新技术学习开始了");
beginTime = System.currentTimeMillis();

}

}
package lqq.heima.day3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class ProxyTest2 {

/**
* @param args
*/
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// TODO Auto-generated method stub
final ArrayList target = new ArrayList();
Collection proxy2 = (Collection) getProxy(target,new MyAdvice());
proxy2.add("zxx");
proxy2.add("lhm");
proxy2.add("bxd");
System.out.println(proxy2.size());
}

private static Object getProxy(final Object target, final Advice advice) {
Object proxy2 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
/*new Class[]{Collection.class},*/
target.getClass().getInterfaces(),
new InvocationHandler(){

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub

/*long beginTime = System.currentTimeMillis();
Object retVal = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");
return retVal;*/
//return method.invoke(proxy, args);/*此处如果这样返回调用会形成死循环:我们的类中调用了代理的方法,代理的方法将调用该代理的代理对象、方法名称、和方法的参数传递给类了handler的invoke方法,我们又再handler的invoke方法中调用method的invoke方法将目标回设置成代理对象,造成死循环*/

advice.beforeMethod(method);
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;

}

});
return proxy2;
}

}

实现AOP功能的封装与配置

·工厂类BeanFactory负责创建目标类或代理类的实例对象,并通过配置文件实现切换。其getBean方法根据参数字符串返回一个相应的实例对象,如果参数字符串在配置文件中对应的类名不是ProxyFactoryBean,则直接返回该类的实例对象,否则,返回该类实例对象的getProxy方法返回的对象。
·BeanFactory的构造方法接收代表配置文件的输入流对象,配置文件格式如下:
#xxx=java.util.ArrayList
xxx=lqq.heima.day3.aopframework.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=lqq.heima.day3.MyAdvice
·ProxyFactoryBean充当封装生成动态代理的工厂,需要为工厂类提供哪些配置参数信息?
-目标
-通知
·编写客户端应用:
-编写实现Advice接口的类和在配置文件中进行配置
-调用BeanFactory获取对象。
package lqq.heima.day3;

import java.lang.reflect.Method;

public interface Advice {

void beforeMethod(Method method);
void afterMethod(Method method);

}
package lqq.heima.day3;

import java.lang.reflect.Method;

public class MyAdvice implements Advice {

long beginTime = 0;
@Override
public void afterMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("张孝祥Java高新技术学习完成了");
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");

}

@Override
public void beforeMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("张孝祥Java高新技术学习开始了");
beginTime = System.currentTimeMillis();

}

}
package lqq.heima.day3.aopframework;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import lqq.heima.day3.Advice;

public class ProxyFactoryBean {
private Advice advice;
private Object target;

public Advice getAdvice() {
return advice;
}

public void setAdvice(Advice advice) {
this.advice = advice;
}

public Object getTarget() {
return target;
}

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

public Object getProxy() {
// TODO Auto-generated method stub
Object proxy2 = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
/*new Class[]{Collection.class},*/
target.getClass().getInterfaces(),
new InvocationHandler(){

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub

/*long beginTime = System.currentTimeMillis();
Object retVal = method.invoke(target, args);
long endTime = System.currentTimeMillis();
System.out.println(method.getName()+" 方法调用共耗时:" +(endTime -beginTime)+" 毫秒");
return retVal;*/
//return method.invoke(proxy, args);/*此处如果这样返回调用会形成死循环:我们的类中调用了代理的方法,代理的方法将调用该代理的代理对象、方法名称、和方法的参数传递给类了handler的invoke方法,我们又再handler的invoke方法中调用method的invoke方法将目标回设置成代理对象,造成死循环*/

advice.beforeMethod(method);
Object retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;

}

});
return proxy2;
}

}
package lqq.heima.day3.aopframework;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import lqq.heima.day3.Advice;

public class BeanFactory {
Properties props = new Properties();
public BeanFactory(InputStream ips){
try {
props.load(ips);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

@SuppressWarnings("unchecked")
public Object getBean(String name){
Object bean =null;
String className = props.getProperty(name);
try {
Class clazz = Class.forName(className);
bean = clazz.newInstance();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(bean instanceof ProxyFactoryBean){
ProxyFactoryBean proxyFactoryBean =(ProxyFactoryBean)bean;
Object proxy = null;
try {
Advice advice = (Advice) Class.forName(props.getProperty(name+".advice")).newInstance();
Object target = Class.forName(props.getProperty(name+".target")).newInstance();
proxyFactoryBean.setAdvice(advice);
proxyFactoryBean.setTarget(target);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
proxy = (proxyFactoryBean).getProxy();
return proxy;
}
return bean;
}

}
下面是config.properties配置文件的内容:
#package lqq.heima.day3.aopframework;
xxx=java.util.ArrayList
#xxx=lqq.heima.day3.aopframework.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=lqq.heima.day3.MyAdvice
package lqq.heima.day3.aopframework;

import java.io.InputStream;
import java.util.Collection;

public class AopFrameworkTest {

/**
* @param args
*/
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// TODO Auto-generated method stub
InputStream ips = AopFrameworkTest.class.getResourceAsStream("config.properties");
Object bean = new BeanFactory(ips).getBean("xxx");
System.out.println(bean.getClass().getName());
Collection col = (Collection) bean;
col.add("123");
System.out.println("col.size() is:"+col.size());

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐