在介绍动态代理之前,先了解一下什么叫静态代理。
静态代理与动态代理都是代理,代理是对原功能的增强。
静态代理示例代码
public interface Person {
void rentHouse();
}
class RentSeeker implements Person {
@Override
public void rentHouse() {
System.out.println("我想租个大房子");
}
}
class HouseAgent implements Person {
private Person person;
HouseAgent(Person person) {
this.person = person;
}
@Override
public void rentHouse() {
person.rentHouse();
System.out.println("我是房屋中介,我来带您看房");
}
}
class Test {
public static void main(String[] args) {
// 寻租人通过房租中介租房
new HouseAgent(new RentSeeker()).rentHouse();
}
}
结果
类图
缺点:每次新增一个对象类型的时候,我们都需要重新实现一个代理类。代码重用性差。
动态代理静态代理与动态代理的区别主要在于动态代理是在运行时动态生成的,在编译完成后没有具体的class文件,是在运行时动态生成并加载到JVM中,而静态代理的代理类是个具体的class文件。
动态代理主要分为两种:CGLIB动态和JDK动态代理
JDK动态代理我们先将上面的示例用JDK动态代理实现一遍
public interface Person {
void rentHouse();
}
class RentSeeker implements Person {
@Override
public void rentHouse() {
System.out.println("我想租个大房子");
}
}
class Test {
public static void main(String[] args) {
// 寻租人通过房租中介租房
// new HouseAgent(new RentSeeker()).rentHouse();
RentSeeker rentSeeker = new RentSeeker();
Person p = (Person) Proxy.newProxyInstance(RentSeeker.class.getClassLoader(),
new Class[]{Person.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object o = method.invoke(rentSeeker, args);
System.out.println("我是房屋中介,我来带您看房");
return o;
}
});
p.rentHouse();
}
}
CGLIB动态代理
CGLIB是一个第三方类库,运行时动态生成一个子类对象来实现对目标对象功能的扩展。
同样的例子再使用cglib实现一遍。
public class CgLibTest {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RentSeeker.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
Object o = proxy.invokeSuper(obj, args);
System.out.println("我是房屋中介,我来带您看房");
return o;
}
});
RentSeeker sample = (RentSeeker) enhancer.create();
sample.rentHouse();
}
}
class RentSeeker {
public void rentHouse() {
System.out.println("我想租个大房子");
}
}
总结
看例子就能看出来,JDK动态代理需要被代理类实现一个或多个接口,而CGLIB不需要。
动态代理使用反射API操作,生成类比较高效,CGLIB使用ASM框架对字节码操作,在类的执行过程中比较高效。



