Java小技巧:使用动态代理实现单例的访问控制

25 阅读1分钟

概述

工作中,有时需要将代码打包成库提供给第三方使用,代码里可能包含一个单例模式实现的类,持有一些重要资源或者不想让外部调用的私有方法,但是调用方可以用反射强行调用。本文使用代理模式中的动态代理来实现访问控制,防止这类非法访问。

实现

  1. 定义接口

    interface IManager{
        int getField();//测试用接口方法
    
        void doMethod();//测试用接口方法
    }
    
  2. 实现类实现该接口

    public class Manager implements IManager {
        private static IManager instance;//代理实例
        private Manager(){
    
        }
    
        public static synchronized IManager getInstance(){
            if(instance == null){
                final Manager manager = new Manager();//真实的实例
                instance = (IManager) Proxy.newProxyInstance(Manager.class.getClassLoader(), new Class[]{IManager.class}, new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        return method.invoke(manager, args);
                    }
                });//创建动态代理的实例,通过闭包访问真实的实例,无法通过其他方式访问该实例。
            }
            return instance;
        }
    
        /* test: 提供测试用的field和method*/
        private int id = hashCode();
    
        @Override
        public int getField() {
            return id;
        }
    
        @Override
        public void doMethod() {
            System.out.println("doMethod:" + id);
        }
    }
    
  3. 使用示例

    public class Main {
        public static void main(String[] args) {
            IManager manager = Manager.getInstance();
            System.out.println("id:" + manager.getField());
            manager.doMethod();
        }
    }