代理模式(Proxy Pattern):代理模式是 Java 常见的设计模式之一。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代理对象,来间接的调用实际的对象。通俗的来讲代理模式就是我们生活中常见的中介。
代理模式可以分为两种:静态代理、动态代理。
静态代理模式由三个部分构成:
//公共接口
public interface Rent {
void renting();
}
//被代理对象
public class Corey implements Rent{
//这是被代理对象!(房主)
@Override
public void renting() {
System.out.println("Corey有房出租");
}
}
//代理对象(中介)
public class StaticProxyRent implements Rent{
private Rent rent;
public StaticProxyRent(Rent rent){
this.rent = rent;
}
@Override
public void renting() {
System.out.println("向房客出租房屋");
this.rent.renting();
System.out.println("完成售后服务");
}
}
public class StaticProxyTest {
public static void main(String[] args) {
Rent rent = new Corey();
StaticProxyRent staticProxyRent = new StaticProxyRent(rent);
staticProxyRent.renting();
}
}
在动态代理中分为两种实现方式:
public interface JdkProxyRent {
void renting();
}
public class JdkProxyCorey implements JdkProxyRent {
@Override
public void renting() {
System.out.println("Corey 有房出租!");
}
}
//动态生成代理对象的工厂
public class JdkProxyFactory {
//动态生成代理对象
public static Object getProxyBean(Object target){
Class clazz = target.getClass();
MyAspect myAspect = new MyAspect();
//在JDK中动态生成代理对象的方法
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
//动态生成代理对象的方法
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
myAspect.before();
Object obj = method.invoke(target,args);
myAspect.after();
return obj;
}
});
}
}
public class MyAspect {
public void before(){
System.out.println("带领房客看房...签租房协议");
}
public void after(){
System.out.println("售后服务");
}
}
public class jdkProxyTest {
public static void main(String[] args) {
JdkProxyRent jdkProxyRent = new JdkProxyCorey();
JdkProxyRent jdkProxyRent1 =(JdkProxyRent)JdkProxyFactory.getProxyBean(jdkProxyRent);
jdkProxyRent1.renting();
}
}
CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它被许多框架所使用,其底层是通过使用一个小而快的字节码处理框架 ASM(Java 字节码操控框架)转换字节码并生成新的类。因此 CGLIB 要依赖于 ASM 的包。
JDK 的动态代理机制只能代理实现了接口的类,而对于没有实现接口的类就不能使用JDK 的 Proxy 类生成代理对象,cglib 是针对类来实现代理的,他的原理是对指定的目标类生成一个子类并通过回调的方式来实现增强,但因为采用的是继承,所以不能对 final 修饰的类进行代理。
cglib.jar
asm.jar
public interface CglibProxyRent {
void renting();
}
public class CglibProxyCorey implements CglibProxyRent {
@Override
public void renting() {
System.out.println("Corey 有房出租");
}
}
public class CglibProxyBeanFactory {
public static Object getProxyBean(CglibProxyRent rent){
CglibMyAspect myAspect = new CglibMyAspect();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(rent.getClass());
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
myAspect.before();
Object obj = method.invoke(rent,objects);
myAspect.after();
return obj;
}
});
return enhancer.create();
}
}
public class CglibMyAspect {
public void before(){
System.out.println("带领客户看房,签订租房协议");
}
public void after(){
System.out.println("售后服务");
}
}
public class Test {
public static void main(String[] args) {
CglibProxyRent rent = new CglibProxyCorey();
CglibProxyRent rent1 = (CglibProxyRent) CglibProxyBeanFactory.getProxyBean(rent);
rent1.renting();
}
}