1.静态代理
接口
package ProxyDemo.staticProxy;
public interface Person {
void findJob();
}
委托类
package ProxyDemo.staticProxy;
public class Tom implements Person{
@Override
public void findJob() {
System.out.println("我要找工作!静态代理!");
}
}
静态代理类
package ProxyDemo.staticProxy;
/**
* 静态代理 自己创建代理类,调用之前代理类已经存在
*
* 缺点:
* 代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。
* 这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。
* 增加了代码维护的复杂度。不符合开闭原则
*
* 代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理
*
*/
public class StaticProxy implements Person {
private Person person;
public StaticProxy(Person person) {
this.person = person;
}
@Override
public void findJob() {
before();
person.findJob();
after();
}
public void before(){
System.out.println("调用之前增强!静态代理");
}
public void after(){
System.out.println("调用之后增强!静态代理");
}
}
2.JDK动态代理
接口
public interface Person {
void findJob();
}
委托类
package ProxyDemo.JDKDynamic;
public class Jim implements Person {
@Override
public void findJob() {
System.out.println("我要找工作!");
}
}
JDK动态代理类
package ProxyDemo.JDKDynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* 动态代理
* 最大的特点是 符合开闭原则 当被代理的对象修改后 代理类不会修改
* 动态代理类是在运行的时候 动态的生成一个代理类 通过反射的方式调用方法的
*
* 基于jdk的动态代理
* 1.必须实现InvocationHandler 这个接口
* 2.被代理的对象的父类必须是接口 jdk动态代理是根据接口获取被代理的对象的所有的方法
*
*/
public class JDKDynamicProxy implements InvocationHandler {
//接口
private Object object;
public Object getInstance(Object target){
object = target;
Class<?> clazz = target.getClass();
/**
* public static Object newProxyInstance(
* ClassLoader loader, 类加载器
* Class<?>[] interfaces, 获取所有实现的接口
* InvocationHandler h) 当前类 在生成的代理类中会调用线面InvocationHandler invoke方法 用来增强被代理对象
*/
return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//增强操作
before();
Object o = method.invoke(object,args);
//增强操作
after();
return o;
}
public void before(){
System.out.println("调用之前增强!");
}
public void after(){
System.out.println("调用之后增强!");
}
}
3.CGLIB动态代理
委托类
package ProxyDemo.CGLIBProxy;
public class Shawn {
public void findJob() {
System.out.println("我要找工作!");
}
}
CGLIB代理类
package ProxyDemo.CGLIBProxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* cglib 动态代理
* 代理的对象 作为被代理对象的子类 通过子类调用父类的方法
*
* 会生成3个代理类
* 1个类集成了被代理的对象
* 另外两个类 生成了被代理类的所有的方法的
* 调用的时候不需要反射调用 调用效率较JDK动态代理的快
*
*/
public class CGLIBProxy implements MethodInterceptor {
private Object object;
public Object createCGLIBProxy(Object object){
this.object = object;
//创建对象
Enhancer enhancer = new Enhancer();
//设置代理的目标类 进行扩展
enhancer.setSuperclass(this.object.getClass());
//设置回调 在回调中拦截对目标方法的调用
enhancer.setCallback(this);
//设置类加载器
enhancer.setClassLoader(this.object.getClass().getClassLoader());
//创建代理对象
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before();
Object oo = methodProxy.invoke(object,objects);
after();
return oo;
}
public void before(){
System.out.println("调用之前增强!");
}
public void after(){
System.out.println("调用之后增强!");
}
}
总结:
静态代理:自己实现代理类,代理之前代理类已经存在。缺点:不符合开闭原则,当你修改被代理对象的时候如增加或删除一个方法,代理对象也要做相应的修改。
动态代理:是在运行的时候,生成代理对象的。符合开闭原则,被代理对象改变的时候,不需要修改代理类。
JDK动态代理:java jdk提供的一个动态代理的方式。1.代理的对象必须实现接口,jdk动态代理是根据接口来获取所有被代理对象的方法 2.需要实现InvocationHandler这个接口,用来生成代理类。
CGLIB代理:被代理类不需要实现接口,被代理类作为代理类的父类。而且可以代理委托类的任意非final修饰的public和protected方法
静态代理和动态代理的目的都是用来扩展被代理类的,都是以重写被代理类的方法的目的来实现的。