高新技术 代理
一、代理
代理架构图:
AOP:面向方面的编程(Aspect oriented program,简称AOP),AOP的目标就是要使交叉业务模块化。可以采用将切面代码移动到原始方法的周围,这与直接在方法中编写切面代码的运行效果是一样的。
动态代理技术:JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用做代理类,即动态代理类。JVM生成的动态代理类必须实现一个或多个接口,所以JVM生成的动态类只能用作具有相同接口的目标类的代理。CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
代理应用:代理类的各个方法中通常除了要调用目标的相应方法和对外返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
1.在调用目标方法之前;
2.在调用目标方法之后;
3.在调用目标方法前后;
4.在处理目标方法异常的catch块中。
练习:实现Collection接口的代理,并查看它的方法。
package cn.itcast.day3;
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;
public class ProxyTest {
public static void main(String[] args) throws Throwable {
// TODO Auto-generated method stub
Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
Constructor[] constructors = clazz.getConstructors();
System.out
.println("--------------Constructor list--------------");
for(Constructor constructor : constructors){
StringBuilder sb = new StringBuilder();
sb.append(constructor.getName()+"(");
Class[] types = constructor.getParameterTypes();
for(Class type : types){
sb.append(type.getSimpleName()+",");
}
if(types.length!=0&&types!=null){
sb.deleteCharAt(sb.length()-1);
}
System.out.println(sb.toString()+")");
}
Method[] methods = clazz.getMethods();
System.out
.println("--------------Method list--------------");
for(Method method : methods){
StringBuilder sb1 = new StringBuilder();
sb1.append(method.getName()+"(");
Class[] types1 = method.getParameterTypes();
for(Class type : types1){
sb1.append(type.getSimpleName()+",");
}
if(types1.length!=0&&types1!=null){
sb1.deleteCharAt(sb1.length()-1);
}
System.out.println(sb1.toString()+")");
}
}
}
创建代理的三种方法:
1.内部类:
package cn.itcast.day3;
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;
public class ProxyTest {
public static void main(String[] args) throws Exception {
Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
Constructor con = clazz.getConstructor(InvocationHandler.class);
class MyInvocationHandler implements InvocationHandler
{
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ArrayList target = new ArrayList();
Object retVal = method.invoke(target, Object.class);
System.out.println(method.getName());
return retVal;
}
}
Collection coll = (Collection) con.newInstance(new MyInvocationHandler());
coll.add("a");
coll.add("b");
coll.add("c");
coll.remove("a");
}
}
2.匿名内部类:
package cn.itcast.day3;
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;
public class ProxyTest {
public static void main(String[] args) throws Exception {
Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
Constructor con = clazz.getConstructor(InvocationHandler.class);
Collection coll = (Collection) con.newInstance(new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ArrayList target = new ArrayList();
Object retVal = method.invoke(target, Object.class);
System.out.println(method.getName());
return retVal;
}
});
coll.add("a");
coll.add("b");
coll.add("c");
coll.remove("a");
}
}
3.Proxy的newProxyInstance方法:
package cn.itcast.day3;
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;
public class ProxyTest {
public static void main(String[] args) throws Exception {
Collection coll = (Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ArrayList al = new ArrayList();
Object retVal = method.invoke(al, args);
System.out.println(method.getName());
return retVal;
}
});
coll.add("a");
coll.add("b");
coll.add("c");
coll.remove("a");
}
}
为代理添加显示运行时间功能:
package cn.itcast.day3;
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;
public class ProxyTest {
public static void main(String[] args) throws Exception {
Collection coll = (Collection) Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ArrayList al = new ArrayList();
long begin = System.currentTimeMillis();
Object retVal = method.invoke(al, args);
long end = System.currentTimeMillis();
System.out.println(method.getName()+" time of "+(end-begin));
return retVal;
}
});
coll.add("a");
coll.add("b");
coll.add("c");
coll.remove("a");
}
}
分析InvocationHandler传递的参数:
客户端程序调用objProxy.add("abc");方法时,涉及三要素:objProxy对象,add方法,“abc”参数。
Object invoke(Object proxy, Method method, Object[] args)
在代理实例上处理方法调用并返回结果。
这正是对应了InvocationHandler传入的三个参数。代理对象,代理对象方法和传递参数。并且将返回值返回给代理对象。
答:通过查阅文档知道,Object类中只有hashCode,equals,toString方法派发给了InvocationHandler,其他方法InvocationHandler自己实现了。
动态代理的工作原理图:
例:
代理
package cn.itcast.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 ProxyTest {
public static void main(String[] args) throws Exception {
final ArrayList al = new ArrayList();
Collection coll = (Collection) getProxy(al,new MyAdvice());
coll.add("a");
coll.add("b");
coll.add("c");
coll.remove("a");
}
private static Object getProxy(final Object al,final Advice ad) {
Object coll = Proxy.newProxyInstance(
al.getClass().getClassLoader(),
al.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ad.before();
Object retVal = method.invoke(al, args);
ad.after(method);
return retVal;
}
});
return coll;
}
}
添加代码到代理的接口:
package cn.itcast.day3;
import java.lang.reflect.Method;
public interface Advice {
void before();
void after(Method method);
}
实现接口的类:
package cn.itcast.day3;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
private long begin;
@Override
public void after(Method method) {
long end = System.currentTimeMillis();
System.out
.println(method.getName() + " time of " + (end - begin));
}
@Override
public void before() {
begin = System.currentTimeMillis();
}
}
根据视频理解自创的小型框架,通过配置文档可切换代理类:
BeanFactory类:
package cn.itcast.test;
import java.io.InputStream;
import java.util.Properties;
import cn.itcast.day3.Advice;
import cn.itcast.day3.MyAdvice;
public class BeanFactory {
public Object getBean(InputStream in) throws Exception{
Properties prop = new Properties();
prop.load(in);
Class clazz = Class.forName(prop.getProperty("xxx"));
if(clazz.getName().equals("cn.itcast.test.ProxyFactoryBean")){
ProxyFactoryBean pfb = (ProxyFactoryBean) clazz.newInstance();
Class targetclass = Class.forName(prop.getProperty("xxx.target"));
Object target = targetclass.newInstance();
Class advaceclass = Class.forName(prop.getProperty("xxx.advice"));
Advice ad = (Advice) advaceclass.newInstance();
return pfb.getProxy(target,ad);
}
return clazz.newInstance();
}
}
ProxyFactoryBean类:package cn.itcast.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import cn.itcast.day3.Advice;
public class ProxyFactoryBean {
public Object getProxy(final Object target,final Advice ad){
Object obj = Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
ad.before();
Object reVal = method.invoke(target, args);
ad.after(method);
return reVal;
}
});
return obj;
}
}
Advice接口:package cn.itcast.day3;
import java.lang.reflect.Method;
public interface Advice {
void before();
void after(Method method);
}
MyAdvice类:package cn.itcast.day3;
import java.lang.reflect.Method;
public class MyAdvice implements Advice {
private long begin;
@Override
public void after(Method method) {
long end = System.currentTimeMillis();
System.out
.println(method.getName() + " time of " + (end - begin));
}
@Override
public void before() {
begin = System.currentTimeMillis();
}
}
config.properties配置文档:#xxx=java.util.ArrayList
xxx=cn.itcast.test.ProxyFactoryBean
xxx.target=java.util.ArrayList
xxx.advice=cn.itcast.day3.MyAdvice