概述
在工程中,为了清晰划分接口与实现的概念,我们通过会使用interface和实现了这个interface的类。在变量声明的时候,声明变量的类型为interface的类型,但是实际赋值的是实现了interface的类的实例。从而达到静态代理的目的。
在实现的项目开发中,我们可能希望代理的功能更强大,特别是在多模块项目中。我们使用两层嵌套的静态代理来模仿ServiceManger管理一系列后台服务,具体流程如下:
- 定义一个App全局的Service的管理接口: 抽象类AppService
public abstract class AppService {
protected static AppService instance;
public static Context context;
public AppService() {
}
@NonNull
public static <T> T getService(Class<T> clazz) {
return instance.getServiceImpl(clazz);
}
@NonNull
public static <T> T getService(Class<T> clazz, boolean isNeedNewObject) {
return instance.getServiceImpl(clazz, isNeedNewObject);
}
@NonNull
protected abstract <T> T getServiceImpl(Class<T> var1);
@NonNull
protected abstract <T> T getServiceImpl(Class<T> var1, boolean var2);
}
AppService的抽象功能是后台服务路由。AppService是一个抽象类,所以具体的路由实现是由子类来完成的。但是AppService有一个AppService静态变量instance,一旦子类实例化并赋值给instance,我们就可以通过如下方式调用后台服务:
AppService.getService(ILauch.class).goLogin();
这里的AppService其实和系统的ServiceManager类似,管理了一系列的后台服务。下面看下他的实现类:
public final class AppServiceImp extends AppService {
private static HashMap<String, Object> services = new HashMap<>();
private AppServiceImp() {
}
public synchronized static YoucaiService getInstance() {
if (instance == null)
instance = new AppServiceImp();
return instance;
}
@Override
protected @NonNull <T> T getServiceImpl(Class<T> clazz) {
String className = clazz.getName();
if (!services.containsKey(className)) {
createService(className);
}
return (T) services.get(className);
}
@Override
protected @NonNull <T> T getServiceImpl(Class<T> clazz, boolean isNeedNewObject) {
String cn = clazz.getName();
if (!services.containsKey(cn)) {
createService(cn);
}
if (!isNeedNewObject) {
return (T) services.get(cn);
} else {
try {
return (T) (services.get(cn).getClass().newInstance());
} catch (InstantiationException e) {
return null;
} catch (IllegalAccessException e) {
return null;
}
}
}
/*根据类型路由到对应的服务实现类*/
private void createService(String cName) {
if (ILaunch.class.getName().equals(cName)) {
services.put(cName, LaunchImp.getInstance());
} else if (IDownload.class.getName().equals(cName)) {
...
}
}
}
这里我们在Application初始化的时候,调用AppServiceImpl.getInstance()
方法初始化AppService,这时候AppService的instance已经是AppServiceImpl的实例。
如何在多模块项目中使用AppService的这套机制
先假设项目有如下模块:base模块(library模块),mobile模块(Application模块,可以打apk,会依赖其他个人模块),other模块(其他功能模块,会依赖base模块)。
- base模块:我们在base模块中,定义AppService这个抽象类以及ILaunch等服务接口。这样在other模块中就可以通过AppService和ILaunch接口对服务进行访问。
- mobile模块:主模块,可打包整个项目。AppServiceImpl,LaunchImpl都是在这里实现的。
- other模块:业务功能模块,依赖base模块,会调用服务。通过如下方式调用:
AppService.getService(ILauch.class).goLogin()
使用动态代理实现
上述使用了静态代理的方法实现了类似ServiceManager的机制。下面介绍改用动态代理的方式实现。动态代理就不需要Service服务分发这一步了,直接使用注解来表示不同的服务。
- 首先还是在base中定义AppService接口
public interface AppService {
//******************** 账号相关业务接口 **************************************
@Account
void goLogin();
@Account
void getUserInfo(CSCallback<CSModel> callback);
@Account
boolean isLogin();
//******************** 下载相关业务接口 ***********************************
@Download
void goDownload(String url);
}
这里将服务的类型转用了注解的形式表示。
- 在mobile模块中实现APPServiceImpl
public class AppServiceImpl { private DownloadManager downloadManager; private LaunchManager launchManager; public AppServiceImpl() { this.downloadManager = new DownloadManager(); this.launchManager = new LaunchManager(); } public <T> T create(final Class<T> service) { validateServiceInterface(service); return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // If the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } return proxyRoute(method, args); } }); } /** 服务,以及具体的服务方法代理*/ private <T> T proxyRoute(Method method, @Nullable Object[] args) { if (method.isAnnotationPresent(Account.class)) { if (method.getName().equals("isLogin")) { return (T) launchManager.isLogin(); }else if (method.getName().equals("getUserInfo")) { launchManager.getUserInfo((CSCallback<CSModel>) args[0]); } }else if (method.isAnnotationPresent(Download.class)) { if (method.getName().equals("goDownload")) { return (T)certificationManager.goDownload((String) args[0]); } } return null; } static <T> void validateServiceInterface(Class<T> service) { if (!service.isInterface()) { throw new IllegalArgumentException("API declarations must be interfaces."); } // Prevent API interfaces from extending other interfaces. This not only avoids a bug in // Android (http://b.android.com/58753) but it forces composition of API declarations which is // the recommended pattern. if (service.getInterfaces().length > 0) { throw new IllegalArgumentException("API interfaces must not extend other interfaces."); } } }
上述代码已经实现了AppService从Client接口到具体Service、具体Service方法的代理。下面只要创建DownloadManager、LaunchManager实现具体方法即可。
- 为了在other模块使用,我们在base模块定义AppServiceClient抽象类:
public abstract class AppServiceClient {
private static AppService appService;
public static AppService getAppService() {
return appService;
}
public abstract AppService bindAppService();
在mobile模块Application初始化的时候,初始化一个AppServiceClientImpl:
public class AppServiceClientImpl extend AppServiceClient {
public static init() {
if(null == appService) {
new AppServiceClientImpl();
}
}
private AppServiceClientImpl(){
getAppService();
};
public AppService bindAppService() {
if (null == appService) {
AppServiceImpl serviceImpl = new AppServiceImpl();
appService = serviceImpl.create(AppService.class);
}
return appService;
}
AppServiceClientImpl.init();
在other模块调用方式如下:
AppServiceClient.getAppService().goLogin();