Proxy(代理) AOP(面向切面编程)
a) 为程序中具有多个相同接口的目标类各增加一些系统功能.例如.异常处理,日志,计算方法的运行时间.事物管理,等待.
b) AOP系统中存在交叉业务(安全,事物,日志),每个交叉业务要贯穿系统中的每个模块,代理就是实现AOP功能的核心技术和关键技术
c) 动态代理.JVM可以在运行期动态的生成出类的字节码,这种动态生成的类用作代理,
d) JVM生成的动态类必须实现一个或者多个接口,所以JVM生成的动态类只能用作具有相同接口目标类的代理。
e) CGLIB库可以动态生成没有接口类的子类,一个类的子类也可以用作该类的代理,所以使用CGLIB也可以实现代理。
package com.enhance.proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
/**
* 使用代理创建对象 并获取对象的各种属性
* InvocationHandler
* Object 只将 hashCode toString equals() 委托给 InvocationHandler 处理,其他的 方法没有委托给InvocationHandler 处理
*/
public class ProxyTest {
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception{
// TODO Auto-generated method stub
Class clazzProxy=Proxy.getProxyClass(Collection.class.getClassLoader(),Collection.class);
System.out.println(clazzProxy.getName());
System.out.println("---------begin constructor list---------");
Constructor[] constructors=clazzProxy.getConstructors();
for (Constructor constructor : constructors) {
String name=constructor.getName();
StringBuilder sbr=new StringBuilder(name);
sbr.append('(');
Class[] clazzParams=constructor.getParameterTypes();
for (Class clazzParam : clazzParams) {
sbr.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null && clazzParams.length>0)
sbr.deleteCharAt(sbr.length()-1);
sbr.append(')');
System.out.println(sbr.toString());
}
System.out.println("---------begin Method list---------");
Method[] methods=clazzProxy.getMethods();
for (Method method : methods) {
String name=method.getName();
StringBuilder sbr=new StringBuilder(name);
sbr.append('(');
Class[] clazzParams=method.getParameterTypes();
for (Class clazzParam : clazzParams) {
sbr.append(clazzParam.getName()).append(',');
}
if(clazzParams!=null && clazzParams.length>0)
sbr.deleteCharAt(sbr.length()-1);
sbr.append(')');
System.out.println(sbr.toString());
}
System.out.println("---------begin Create Object ---------");
//第一种写法
Constructor con=clazzProxy.getConstructor(InvocationHandler.class);
class MyInvocationHandler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
}
Collection poxy1=(Collection)con.newInstance(new MyInvocationHandler());
System.out.println(poxy1);
System.out.println(poxy1.toString());//对象不为空,但是 tostring()返回的是null 是因为 invoke返回的是null 所以就是null.
poxy1.clear(); //能成功调用
// poxy1.size(); //不能成功调用 NullException 原因 就是 上面的 InvocationHandler 的invoke 返回的是 null ,而 size 要返回的是int ,无法将null 转换成 int类型 所以就异常了
//第二种写法
Collection poxy2=(Collection)con.newInstance(new InvocationHandler(){
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return null;
}
});
//第三种写法
Collection proxy3=(Collection)Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler(){
ArrayList target=new ArrayList();
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//使用代理 来获取方法执行的时间
//或者 使用过滤器 来过滤 用户的非法内容
//或者 加入日志 加入事务 等等
long stime=System.currentTimeMillis();
Thread.sleep(10);
Object retVal=method.invoke(target, args);
long etime=System.currentTimeMillis();
System.out.println(method.getName()+" runing time is "+(etime-stime));
return retVal;
}
});
Object obj= proxy3.add("zxx");
System.out.println("returnVal :"+obj);
proxy3.add("lhm");
proxy3.add("bxd");
System.out.println(proxy3.size());
//接下来 将 上面的方法 抽取一个公共方法.
}
}
简单的代理
package com.enhance.proxy;
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 ProxyUtil {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final ArrayList list=new ArrayList();
Collection proxy=(Collection)getProxy(list, new MyAdvice());
proxy.add("zxx");
proxy.add("lhm");
proxy.add("bxd");
System.out.println(proxy.size());
}
public static Object getProxy(final Object target,final Advice 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 val=method.invoke(target, args);
advice.afterMethod(method);
return val;
}
});
return proxy;
}
}
package com.enhance.proxy;
import java.lang.reflect.Method;
public interface Advice {
void beforeMethod(Method method); //方法之前运行的代码
void afterMethod(Method method); //方法之后运行的嗲吗
void exceptionMethod(Method method); //方法异常运行的代码
void beforeAfterMethod(Method method);//方法前后运行的代码
}
//------------------------------------------
package com.enhance.proxy;
import java.lang.reflect.Method;
public class MyAdvice implements Advice{
long etime=0;
long stime=0;
@Override
public void beforeMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("开始学习啦!");
stime=System.currentTimeMillis();
}
@Override
public void afterMethod(Method method) {
// TODO Auto-generated method stub
System.out.println("学习结束了!");
etime=System.currentTimeMillis();
System.out.println(method.getName()+" runing time is "+(etime-stime));
}
@Override
public void exceptionMethod(Method method) {
// TODO Auto-generated method stub
}
@Override
public void beforeAfterMethod(Method method) {
// TODO Auto-generated method stub
}
}
//mini AOPFreamework
package com.enhance.proxy.aopfreamwork;
import java.io.InputStream;
public class AopFrameworkTest {
/**
* @param args
*/
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());
}
}
package com.enhance.proxy.aopfreamwork;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import com.enhance.proxy.Advice;
public class BeanFactory {
private Properties props=new Properties();
public BeanFactory(InputStream ips) {
try {
props.load(ips);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Object getBean(String name){
String className=props.getProperty(name);
Object bean=null;
try {
Class clazz=Class.forName(className);
bean=clazz.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
if(bean instanceof ProxyFactoryBean){
ProxyFactoryBean proxyBean=((ProxyFactoryBean)bean);
Advice advice=null;
Object target=null;
try {
advice=(Advice)Class.forName(props.getProperty(name+".advice")).newInstance();
target = Class.forName(props.getProperty(name+".target")).newInstance();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
proxyBean.setAdvice(advice);
proxyBean.setTarget(target);
Object proxy=proxyBean.getProxy();
return proxy;
}
return bean;
}
}
package com.enhance.proxy.aopfreamwork;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import com.enhance.proxy.Advice;
public class ProxyFactoryBean {
private Advice advice;
private Object target;
public Object getProxy() {
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 val=method.invoke(target, args);
advice.afterMethod(method);
return val;
}
});
return proxy;
}
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;
}
}
//配置文件
#xxx=java.util.ArrayList
xxx=com.enhance.proxy.aopfreamwork.ProxyFactoryBean
xxx.advice= com.enhance.proxy.MyAdvice
xxx.target=java.util.ArrayList