为某对象提供一种代理以控制对该对象的访问。即客户端通过代理间接地访问该对象,从而限制、增强或修改该对象的一些特性。
【三种实现形式】
- 静态代理:要求被代理对象需要实现接口或继承父类,我们的代理对象与被代理对象一起实现相同的接口或继承相同父类。
- JDK动态代理:通过Jdk自带的Proxy类来实现,原理是实现了被代理对象的接口。要求被代理对象需要实现接口,但是我们的代理对象不需要实现接口。
- Cglib动态代理:也叫子类代理,通过额外引用Cglib包来实现,原理是继承了被代理对象。对被代理对象没有什么要求,不需要实现接口或继承父类。
【代理模式(静态)VS 装饰模式】
- 相同点:都需要实现同一个接口或者继承同一个抽象类,并且代理角色和装饰角色都持有被代理角色和构件角色的引用。
不同点:代理模式重点在于控制对象的行为,而装饰模式侧重于增加对象的职能。通俗的讲,它们俩根本的区别是目的性不一样,也就是使用场景。
/*** 老师*/public interface Teacher {void teach();}
/*** 老师 实现类*/public class TeacherImpl implements Teacher {@Overridepublic void teach() {System.out.println("老师开始讲课...");}}
【静态代理】
/*** 老师 - 静态代理类*/public class TeacherStaticProxy implements Teacher {private Teacher teacher;public TeacherStaticProxy(Teacher teacher) {this.teacher = teacher;}@Overridepublic void teach() {System.out.println("[静态代理]上课前起立");teacher.teach();System.out.println("[静态代理]下课后起立");}}
【JDK动态代理】
/*** 老师 - JDK动态代理类*/public class TeacherDynamicProxy {private Teacher teacher;public TeacherDynamicProxy(Teacher teacher) {this.teacher = teacher;}public Teacher getProxy() {return (Teacher) Proxy.newProxyInstance(teacher.getClass().getClassLoader(), teacher.getClass().getInterfaces(), new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("[JDK动态代理]上课前起立");Object obj = method.invoke(teacher, args);System.out.println("[JDK动态代理]下课后起立");return obj;}});}}
【Cglib动态代理】
/*** 老师 - Cglib动态代理类*/public class TeacherCglibProxy implements MethodInterceptor {private Teacher teacher;public TeacherCglibProxy(Teacher teacher) {this.teacher = teacher;}public Teacher getProxy() {// 1. 使用Enhancer创建代理类Enhancer enhancer = new Enhancer();// 2. 继承被代理类enhancer.setSuperclass(teacher.getClass());// 3. 设置回调enhancer.setCallback(this);// 4. 生成代理对象return (Teacher) enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("[Cglib动态代理]上课前起立");Object obj = method.invoke(teacher, objects);System.out.println("[Cglib动态代理]下课后起立");return obj;}}
public class ProxyTest {public static void main(String[] args) {Teacher teacher = new TeacherImpl();// 静态代理TeacherStaticProxy staticProxy = new TeacherStaticProxy(teacher);staticProxy.teach();System.out.println();// JDK动态代理TeacherDynamicProxy dynamicProxy = new TeacherDynamicProxy(teacher);dynamicProxy.getProxy().teach();System.out.println();// Cglib动态代理TeacherCglibProxy cglibProxy = new TeacherCglibProxy(teacher);cglibProxy.getProxy().teach();}}----输出----[静态代理]上课前起立老师开始讲课...[静态代理]下课后起立[JDK动态代理]上课前起立老师开始讲课...[JDK动态代理]下课后起立[Cglib动态代理]上课前起立老师开始讲课...[Cglib动态代理]下课后起立
