代理:要为已存在的多个具有相同接口的目标类的各个方式增加一些系统功能,
例如,异常处理、日志、计算方法的运行时间、事务管理、等等,
编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标
类的相同方法,并子啊调用方法时加上系统功能的代码.
如果采用工厂模式和配置文件的方式进行管理,则不需要改客户端程序,
在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,如,想要
日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后
运行一段时间后,又想去掉系统功能也很容易。
安全、事务、日志等功能要贯穿到好多模块中,所以,它们就是交叉业务使用代理
JVM可以在运行期间必须实现一个或多个接口,所以,JVM生成的动态类
只能用作具有相同接口的目标类的代理
JCGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的
代理,所以,如果要一个没有实现接口的类生成动态代理类,那么可以使用
CGLIB库。
package com.heima.proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
public class XProxy {
public static void main(String[] argc) {
Class clazzCollection = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
System.out.println(clazzCollection.getName());
//------------begin constructors list------------
Constructor[] constructors = clazzCollection.getConstructors();
for(Constructor constructor : constructors) {
String name = constructor.getName();
StringBuilder sb = new StringBuilder(name);
sb.append("(");
Class[] clazzParameterTypes = constructor.getParameterTypes();
for(Class clazzParam : clazzParameterTypes) {
sb.append(clazzParam.getName()).append(", ");
}
if(clazzParameterTypes != null &&clazzParameterTypes.length != 0) {
sb.deleteCharAt(sb.length() - 1);
}
sb.append(")");
System.out.println(sb.toString());
}
//------------begin methods list------------
Method[] methodMethod = clazzCollection.getMethods();
for(Method method : methodMethod) {
String name = method.getName();
StringBuilder sbM = new StringBuilder(name);
sbM.append("(");
Class[] clazzParameterTypes = method.getParameterTypes();
for(Class clazzParamMethod : clazzParameterTypes) {
sbM.append(clazzParamMethod.getName()).append(", ");
}
if(clazzParameterTypes != null &&clazzParameterTypes.length != 0) {
sbM.deleteCharAt(sbM.length() - 1);
}
sbM.append(")");
System.out.println(sbM.toString());
}
}
}
StringBuilder和StringBuffer的区别:StringBuilder在单线程中使用效率高,而StringBuffer用在多线程,不用考虑线程安全。
线程用例
package com.heima.proxy;
import java.lang.reflect.Method;
public interface Advice {
void beforeMethod(Method method);
void afterMethod(Method method);
}
package com.heima.proxy;
import java.lang.reflect.Method;
public class AdviceImp implements Advice {
/**
* before方法
*/
@Override
public void beforeMethod(Method method) {
System.out.println("开始-----> 黑马培训");
}
/**
* after方法
*/
@Override
public void afterMethod(Method method) {
System.out.println("结束-----> 黑马培训");
}
}
package com.heima.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ProxyTest {
private static Object getProxy(final Object target, final Advice advice) {
Object proxy3 = Proxy.newProxyInstance(
target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object retVal = null;
advice.beforeMethod(method);
retVal = method.invoke(target, args);
advice.afterMethod(method);
return retVal;
}
});
return proxy3;
}
public static void main(String[] args) throws Exception {
List list = new ArrayList();
Advice advice = new AdviceImp();
Collection proxy3 = (Collection) getProxy(list, advice);
System.out.println(proxy3.getClass().getName());
proxy3.add("hello heima");
System.out.println(proxy3);
}
}