一、回顾
上篇文章,动态代理模式:代理访问接口对象,根据参数,反射出代理类,执行接口方法。
二、注解
通过反射,得到实例,执行注解方法。为什么使用注解呢?
1、一方面减少配置文件,如果自身做过java,肯定知道Spring框架中的@Service,只要在实现类加入@Service,在配置文件写入
<!-- 自动扫描注解的bean --> <context:component-scan base-package="service" />就会自动扫描了。
2、另一方面提高代码效率。比如我们需要创建一个实例,第一想到的是:new一个,这种需求很多的话,一个注解方式,获取实例,就可以大大节省代码量。
@Autowired //注入类,获取实例 private UserDao userDao;三、代码演示
1、普通使用
/** * 注解类 */ @Target(ElementType.METHOD)//作用目标:对方法的注解 @Retention(RetentionPolicy.RUNTIME)//注解保留在运行时的环境中 @Documented//说明该注解将被包含在javadoc中 public @interface GET { String value() default "";//默认返回"" }
/** * 使用类 */ public class GetUtil { @GET("www.baidu.com") void v(){} }
/** * 测试类 */ public class Test { public static void main(String[] args) { System.out.println(getGet(GetUtil.class)); } public static Object getGet(Class<?> clazz){ String result = ""; Method[] m = clazz.getDeclaredMethods(); for(Method ms : m){ if(ms.isAnnotationPresent(GET.class)){//true:包含GET注解 GET get = ms.getAnnotation(GET.class);//获取注解(反射),获取失败,返回null if(get != null){ result= "正在访问后台接口" + get.value();//执行注解方法,假设访问了某个后台接口 } } } return result; } }2、结合动态代理模式使用(如果对动态代理有些模糊,建议先阅读上篇文章或者忽略下面代码)
/** * 注解类 * @author Biligle * */ @Target(ElementType.METHOD)//作用目标:对方法的注解 @Retention(RetentionPolicy.RUNTIME)//注解保留在运行时的环境中 @Documented//说明该注解将被包含在javadoc中 public @interface GET { String value() default "";//默认返回"" }
/** * 公共接口,注解使用类 * @author Biligle * */ public interface IPublicManager { /** * 排水 */ void out(); /** * 发电 */ void power(); /** * 净化 */ @GET("www.huanbao.com/jinghua.json") void clean(String params); }
/** * 生成动态代理,执行接口方法 * @author Biligle * */ public class ProxyUtil implements BasicVoid.VisitListener { public <T> Object create(final Class<T> service){ if(!service.isInterface()){ new IllegalArgumentException("API声明必须是接口"); }else if(service.getInterfaces().length > 0){ new IllegalArgumentException("API接口不能扩展其他接口"); } /** * ClassLoader loader:类加载器 Class<?>[] interfaces:得到全部的接口 InvocationHandler h: */ return Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service}, new InvocationHandler() { /** * proxy 代理对象 * method 接口方法 * args 接口方法的参数 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //无论代理去执行哪个method,首先统一执行一个方法common,之后,在分别执行各自方法 //简言之,这里可以添加公共方法 BasicVoid.get().common(service,method, args).call(ProxyUtil.this); return null; } }); } @Override public void callData(Object obj) { System.out.println("-----------------------------------------------"); System.out.println(obj); System.out.println("-----------------------------------------------"); } }
/** * 代理模式统一执行方法(都是环保公司的业务) * @author Biligle * @param <T> * */ public class BasicVoid<T> { private BasicVoid(){} private static VisitListener listener; private static Object data; public static BasicVoid basicVoid = null; public static BasicVoid get(){ if(basicVoid == null){ basicVoid = new BasicVoid(); } return basicVoid; } public BasicVoid common(Class<T> service, Method method, Object[] args){ data = visit(service,method.getName()); return basicVoid; } /** * 传入接口,用于监听返回数据 * @param l * @return */ public BasicVoid call(VisitListener l){ listener = l; listener.callData(data); return basicVoid; } /** * 统一标准访问,并返回相应数据 * @param method * @return */ private Object visit(Class<T> service, String method){ String lastResult = ""; String base = "统一访问环保公司官网"; Method[] m = service.getDeclaredMethods(); for (Method ms : m) { if(ms.isAnnotationPresent(GET.class)){//true:包含GET注解 GET get = ms.getAnnotation(GET.class);//获取注解(反射),获取失败,返回null if(get != null){ String invokes = "正在访问后台接口" + get.value();//执行注解方法,假设访问了某个后台接口 String result = "这是" + method + "()的访问结果"; lastResult = "执行" + "'" + method + "()'" + "方法" + "\n" + base + "www.huanbao.com" + "\n" + invokes + "......" + "\n" + result; } } } return lastResult; } /** * 获取数据的监听 */ interface VisitListener { /** * 回调数据 * @param obj */ void callData(Object obj); } }
/** * 测试类 * @author Biligle * */ public class Test { public static void main(String[] args) { ProxyUtil p = new ProxyUtil(); IPublicManager iPublic = (IPublicManager) p.create(IPublicManager.class); iPublic.clean("纯净水"); } }