代理模式作用是:在不修改被代理对象功能的基础上,通过对代理类进行扩展,进行一些功能上的附加与增强。如Spring AOP就是用动态代理来实现的。下图可以表述代理模式的流程:
我们在app上看电影的时候会看到很多广告,app厂家拿到电影的代理权限后,再通过穿插各种广告来增加自己的收益,下面通过代理模式来模拟一下
创建代表电影播放的接口
- public interface Movie {
-
- void play();
-
- }
实现电影的播放接口
- public class MovieProxy implements Movie {
-
- private String movieName;
-
- public MovieProxy(String movieName) {
- this.movieName = movieName;
- }
-
- @Override
- public void play() {
- System.out.println("正在播放" + movieName);
- }
- }
创建电影的代理类,表示上述例子中的app
- public class Player implements Movie {
-
- private String movieName;
-
- public Player(String movieName) {
- this.movieName = movieName;
- }
-
- @Override
- public void play() {
- System.out.println("片头广告....");
- MovieProxy movieProxy = new MovieProxy(movieName);
- movieProxy.play();
- System.out.println("片尾广告....");
- }
- }
测试类
- public class Test {
-
- public static void main(String[] args) {
- Player player = new Player("功夫熊猫");
- player.play();
- }
- }
结果

以上就是静态代理的实现,通过拓展代理类进行一些功能的拓展或增强 ,什么叫静态代理呢?就是增强的内容是事先定义好的,如果需要在运行时进行增强就需要用到动态代理。
JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理,用JDK动态代理模拟看电影的例子
创建接口,JDK代理中被代理的对象必须实现接口
- public interface Movie {
-
- void play();
- }
接口实现类
- public class MyMovie implements Movie {
-
- @Override
- public void play() {
- System.out.println("正在播放电影");
- }
- }
测试类
- public class Test {
-
- public static void main(String[] args) {
- // 保存动态代理生成的文件
- System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
- ClassLoader classLoader = MyMovie.class.getClassLoader();
- Class>[] interfaces = MyMovie.class.getInterfaces();
- // proxy代理对象本身
- // method被执行的方法
- // args1方法参数
- Movie movie = (Movie) Proxy.newProxyInstance(classLoader, interfaces, (proxy, method, args1) -> {
- MyMovie myMovie = new MyMovie();
- System.out.println("片头广告");
- Object invoke = method.invoke(myMovie, args1);
- System.out.println("片尾广告");
- return invoke;
- });
- movie.play();
- }
- }
newProxyInstance方法
在此方法中可以分为三个步骤
1)查找或生成指定的代理接口类,如果将sun.misc.ProxyGenerator.saveGeneratedFiles设置为true,则会在com.sun.proxy路径下保存生成的代理类

2)获取构造方法

3)利用反射实例化代理类
cglib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。
创建被代理类
- public class Movie {
-
- public void play() {
- System.out.println("播放电影");
- }
- }
创建回调方法
- public class MyMethodInterceptor implements MethodInterceptor {
-
- @Override
- public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
- System.out.println("片头广告");
- Object o1 = methodProxy.invokeSuper(o, objects);
- System.out.println("片尾广告");
- return o1;
- }
- }
测试类
- public class Test {
-
- public static void main(String[] args) {
- // 生成的代理类存储路径
- System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,".\\code");
- // 在创建Enhancer时会通过动态代理将EnhanceKey创建好,
- Enhancer enhancer = new Enhancer();
- // 设置父类
- enhancer.setSuperclass(Movie.class);
- // 设置回调方法
- enhancer.setCallback(new MyMethodInterceptor());
- // 创建代理类
- Movie movie = (Movie) enhancer.create();
- movie.play();
- }
- }
JDK和CGLIB动态代理的区别: