查看原文
其他

设计模式之动态代理模式实战

Java技术栈 2018-08-26

昨天分享了静态代理的概念及存在的缺点,所以今天讲的动态代理模式十分重要。动态代理在我们工作当中应用相当广泛,如Srping AOP就是动态代理的在开源框架的比较出名的应用。


动态代理有两种试,一是通过JDK自带的API实现动态代理,二是通过别的字节码框架实现,如cglib。


需要注意的是JDK只能针对接口实现动态代理,不能代理普通类,使用具有局限性。而cglib可以代理接口及所有的普通类。


下面拿昨天保存用户信息的例子继续用动态代理来实现。


用户接口

public interface UserInterface {

    boolean saveUser(User user);

}


用户接口实现

public class UserInterfaceImpl implements UserInterface {

    @Override

    public boolean saveUser(User user) {

        System.out.println("保存用户: " + user.getName());

        return true;

    }

}



public class Test {


    public static void main(String[] args) {

        // JDK动态代理

        testJDKProxy();


        // Cglib接口代理

        testCglibInterfaceProxy();


        // Cglib类代理

        testCglibClassProxy();

    }


    private static void testJDKProxy() {

        User user = new User();

        user.setName("tom");

        UserProxy.getUserProxy().saveUser(user);

    }


    static class UserProxy {


        private static final InvocationHandler USER_HANDLE = new InvocationHandler() {


            @Override

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                System.out.println("JDK接口动态代理-开始保存用户");

                Object result = method.invoke(new UserInterfaceImpl(), args);

                System.out.println("JDK接口动态代理-保存用户结果: " + result);

                System.out.println();

                return result;

            }

        };


        public static UserInterface getUserProxy() {

            UserInterface userInterface = (UserInterface) Proxy.newProxyInstance(UserProxy.class.getClassLoader(),

                    new Class[] { UserInterface.class }, USER_HANDLE);

            return userInterface;

        }

    }


    private static void testCglibInterfaceProxy() {

        User user = new User();

        user.setName("tom");

        UserCglibProxy.getUserProxy().saveUser(user);

    }


    static class UserCglibProxy {


        private static final net.sf.cglib.proxy.InvocationHandler USER_HANDLE = new net.sf.cglib.proxy.InvocationHandler() {


            @Override

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                System.out.println("Cglib接口动态代理-开始保存用户");

                Object result = method.invoke(new UserInterfaceImpl(), args);

                System.out.println("Cglib接口动态代理-保存用户结果: " + result);

                System.out.println();

                return result;

            }

        };


        public static UserInterface getUserProxy() {

            UserInterface userInterface = (UserInterface) net.sf.cglib.proxy.Proxy.newProxyInstance(

                    UserCglibProxy.class.getClassLoader(), new Class[] { UserInterface.class }, USER_HANDLE);

            return userInterface;

        }

    }


    private static void testCglibClassProxy() {

        User user = new User();

        user.setName("tom");

        UserInterfaceImpl userImpl = (UserInterfaceImpl) ClassCgLibProxy.getUserProxy(new UserInterfaceImpl());

        userImpl.saveUser(user);

    }


    static class ClassCgLibProxy {


        private static final MethodInterceptor USER_HANDLE = new MethodInterceptor() {


            @Override

            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

                System.out.println("Cglib类动态代理-开始保存用户");

                Object result = proxy.invokeSuper(obj, args);

                System.out.println("Cglib类动态代理-保存用户结果: " + result);

                System.out.println();

                return result;

            }

        };


        public static Object getUserProxy(Object target) {

            Enhancer enhancer = new Enhancer();

            enhancer.setSuperclass(target.getClass());

            enhancer.setCallback(USER_HANDLE);

            return enhancer.create();

        }

    }

}


结果输出:


JDK接口动态代理-开始保存用户

保存用户: tom

JDK接口动态代理-保存用户结果: true


Cglib接口动态代理-开始保存用户

保存用户: tom

Cglib接口动态代理-保存用户结果: true


Cglib类动态代理-开始保存用户

保存用户: tom

Cglib类动态代理-保存用户结果: true


从例子看出,使用也并不复杂,动态代理与静态代理最主要的区别在于,静态代理是编译期间就确定好的代理关系,而动态代理是运行期间由JVM通过反射等技术生成的代理对象,不存在class文件,代理类与被代理类之间的关系是继承关系,所以,普通类final的方法是不能被动态代理的。



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存