静态代理
定以一个学生类,学生有上课和写作业两种行为
public interface Student {
public int attendClass();
public void doHomework();
}
public class StudentImpl implements Student{
@Override
public int attendClass() {
System.out.println("学生上课");
return 1;
}
@Override
public void doHomework() {
System.out.println("学生写作业");
}
}
定义学生代理类
public class StudentProxy implements Student{
private Student student;
public StudentProxy(Student student) {
this.student = student;
}
@Override
public int attendClass() {
System.out.println("坐车上学");
student.attendClass();
return 0;
}
@Override
public void doHomework() {
System.out.println("坐车回家");
student.doHomework();
}
}
测试
@Test
public void testStaticProxy() {
StudentProxy studentProxy = new StudentProxy(new StudentImpl());
studentProxy.attendClass();
studentProxy.doHomework();
}
输出:
坐车上学
学生上课
坐车回家
学生写作业
学生代理类对学生上学和写作业两个动作进行了增强,但是耦合性太强,一个代理类只为一个代理对象服务,代理类需要实现代理对象的接口,维护较为麻烦。
JDK动态代理
代理类实现InvocationHandler接口,在invoke中做增强,运行时生成代理类实现接口进行增强
前提:需要代理类实现实现接口
public class StudentProxyJdk implements InvocationHandler {
// 需要代理的目标类对象
public Object student;
public StudentProxyJdk(Object student) {
this.student = student;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object ret = null;
if ("attendClass".equals(method.getName())) {
System.out.println("坐车上学");
// 调用代理对象的接口
ret = method.invoke(student, args);
} else if ("doHomework".equals(method.getName())) {
System.out.println("坐车回家");
method.invoke(student, args);
}
return ret;
}
}
测试
@Test
public void testJdkProxy() {
Student student = (Student) Proxy.newProxyInstance(StudentImpl.class.getClassLoader(), StudentImpl.class.getInterfaces(), new StudentProxyJdk(new StudentImpl()));
student.attendClass();
student.doHomework();
saveProxy("/xx/xx");
}
// 生成运行时的代理类
private void saveProxy(String path) {
byte[] $Proxies = ProxyGenerator.generateProxyClass("$Proxy2", StudentImpl.class.getInterfaces());
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File(path + "$Proxy2.class"));
fileOutputStream.write($Proxies);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileOutputStream != null) {
try {
fileOutputStream.flush();
fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
运行时生成的代理类
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
import com.wxx.staticProxy.Student;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy2 extends Proxy implements Student {
private static Method m1;
private static Method m4;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy2(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final void doHomework() throws {
try {
super.h.invoke(this, m4, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int attendClass() throws {
try {
return (Integer)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m4 = Class.forName("com.wxx.staticProxy.Student").getMethod("doHomework");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.wxx.staticProxy.Student").getMethod("attendClass");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
cglib动态代理
通过运行时继承代理对象生成代理类来进行增强,不需要实现接口。
使用前需要引入依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
定义一个Star对象
public interface Star {
void sing();
int dance();
}
public class SuperStart implements Star{
@Override
public void sing() {
System.out.println("明星唱歌");
}
@Override
public int dance() {
System.out.println("明星跳舞");
return 0;
}
}
定义拦截器
public class StarCglibInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, org.springframework.cglib.proxy.MethodProxy methodProxy) throws Throwable {
Object ret = null;
if ("sing".equals(method.getName())) {
System.out.println("收钱");
ret = methodProxy.invokeSuper(o, objects);
} else if ("dance".equals(method.getName())) {
System.out.println("收钱");
methodProxy.invokeSuper(o, objects);
}
return ret; }
}
测试
@Test
public void testCglibProxy() {
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "/xxx/xxx/");
CglibInterceptor cglibInterceptor = new CglibInterceptor();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(SuperStart.class);
enhancer.setCallback(cglibInterceptor);
Star star = (Star) enhancer.create();
star.sing();
star.dance();
}