简介
1、定义
为其他对象提供一种代理以控制对这个对象对访问。
2、特点
代理模式关注于对目标方法的控制。代理者拥有控制权限,可以决定目标方法是否调用。
实现方式
1、静态代理
public interface ISubject {
void doSomeThing();
}
public class SubjectImpl implements ISubject {
public void doSomeThing() {
System.out.println("do some thing...");
}
}
public class SubjectProxy implements ISubject {
private ISubject target;
public SubjectProxy(ISubject target) {
this.target = target;
}
public void doSomeThing() {
System.out.println("before....");
target.doSomeThing();
System.out.println("after....");
}
}
2、动态代理
2.1 JDK动态代理
public interface ISubject {
void doSomeThing();
}
public class SubjectImpl implements ISubject {
public void doSomeThing() {
System.out.println("do some thing...");
}
}
public class SubjectJdkProxy implements InvocationHandler {
private ISubject target;
public Object getProxyInstance(ISubject target) {
this.target = target;
Class<? extends ISubject> clazz = target.getClass();
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before...");
method.invoke(target, args);
System.out.println("after...");
return null;
}
}
2.2 CGLIB(Code Generation Library)
public class SubjectImpl {
void doSomething() {
System.out.println("do some thing...");
}
}
public class SubjectCglibProxy implements MethodInterceptor{
public Object getInstance(Class clazz) throws Exception {
Enhancer enhancer = new Enhancer();
// 告诉cglib,生成的子类需要继承哪个类
enhancer.setSuperclass(clazz);
// 设置回调
enhancer.setCallback(this);
// 生成源码,编译成class,加载到JVM中,并返回代理对象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("before...");
methodProxy.invokeSuper(o, objects);
System.out.println("after...");
return null;
}
public class MyTest {
public static void main(String[] args) throws Exception {
SubjectImpl cglibProxy = (SubjectImpl) new SubjectCglibProxy().getInstance(new SubjectImpl().getClass());
cglibProxy.doSomething();
}
}
手写JDK动态代理
自定义ClassLoader
public class MyClassLoader extends ClassLoader{
private File dirPath;
public MyClassLoader(){
String basePath = MyClassLoader.getSystemResource("").getPath();
this.dirPath = new File(basePath);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = MyClassLoader.class.getPackage().getName()+"."+name;
if (dirPath != null) {
File classFile = new File(dirPath, className.replaceAll("\\.", "/")+".class");
if (classFile.exists()) {
FileInputStream fileInputStream = null;
ByteOutputStream outputStream = null;
try {
fileInputStream = new FileInputStream(classFile);
outputStream = new ByteOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = fileInputStream.read(buffer)) != -1){
outputStream.write(buffer, 0, len);
}
return defineClass(className, outputStream.getBytes(), 0, outputStream.size());
}catch (Exception e) {
}finally {
if (fileInputStream != null){
try {
fileInputStream.close();
}catch (Exception e) {
}
}
try {
if (outputStream != null) {
outputStream.close();
}
}catch (Exception e){
}
// classFile.delete();
}
}
}
return null;
}
}
自定义InvocationHandler
public interface MyInvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
自定义Proxy类
public class MyProxy {
public static Object newProxyInstance(MyClassLoader classLoader,
Class<?>[] interfaces,
MyInvocationHandler h){
try{
// 1、生成源代码
String proxySrc = generateSrc(interfaces[0]);
// 2、将生成的源代码输出到磁盘,保存为.java文件
String filePath = MyProxy.class.getResource("").getPath();
File proxyFile = new File(filePath, "$Proxy0.java");
FileWriter fileWriter = new FileWriter(proxyFile);
fileWriter.write(proxySrc);
fileWriter.flush();
fileWriter.close();
// 3、编译源代码,并且生成c.class文件
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null, null, null);
Iterable iterable = manager.getJavaFileObjects(proxyFile);
JavaCompiler.CompilationTask task = javaCompiler.getTask(null, manager,null, null, null, iterable);
task.call();
manager.close();
// 4、将class加载到JVM
Class proxyClass = classLoader.findClass("$Proxy0");
// 5、返回代理对象
Constructor constructor = proxyClass.getConstructor(MyInvocationHandler.class);
return constructor.newInstance(h);
}catch (Exception e){
System.out.println();
}
return null;
}
private static String generateSrc(Class<?> interfaces) {
String enter = "\r\n";
StringBuffer sb = new StringBuffer();
sb.append("package cn.xiaoyanol.learn.design.pattern.proxy.myjdk;"+enter);
sb.append("import java.lang.reflect.Method;"+ enter);
sb.append("public class $Proxy0 implements " + interfaces.getName() + "{" + enter);
sb.append("MyInvocationHandler h;"+ enter);
sb.append("public $Proxy0(MyInvocationHandler h) {" + enter);
sb.append("this.h = h;" + enter);
sb.append("}" + enter);
for (Method m : interfaces.getMethods()) {
sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "(){" + enter);
sb.append("try{" + enter);
sb.append("Method m = " + interfaces.getName() + ".class.getMethod(\"" + m.getName() + "\",new Class[]{});" + enter);
sb.append("this.h.invoke(this,m,null);" + enter);
sb.append("}catch(Throwable e){e.printStackTrace();}" + enter);
sb.append("}" + enter);
}
sb.append("}");
return sb.toString();
}
}