第一个部分- XUtils框架2.0实现:事件注入、资源注入、保存数据注入 1、注入事件 XUtils2.0框架实现

import android.app.Activity;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceGroup;
import android.view.View;
import com.lidroid.xutils.util.LogUtils;
import com.lidroid.xutils.view.EventListenerManager;
import com.lidroid.xutils.view.ResLoader;
import com.lidroid.xutils.view.ViewFinder;
import com.lidroid.xutils.view.ViewInjectInfo;
import com.lidroid.xutils.view.annotation.ContentView;
import com.lidroid.xutils.view.annotation.PreferenceInject;
import com.lidroid.xutils.view.annotation.ResInject;
import com.lidroid.xutils.view.annotation.ViewInject;
import com.lidroid.xutils.view.annotation.event.EventBase;import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class ViewUtils {private ViewUtils() {}public static void inject(View view) {injectObject(view, new ViewFinder(view));}public static void inject(Activity activity) {injectObject(activity, new ViewFinder(activity));}public static void inject(PreferenceActivity preferenceActivity) {injectObject(preferenceActivity, new ViewFinder(preferenceActivity));}public static void inject(Object handler, View view) {injectObject(handler, new ViewFinder(view));}public static void inject(Object handler, Activity activity) {injectObject(handler, new ViewFinder(activity));}public static void inject(Object handler, PreferenceGroup preferenceGroup) {injectObject(handler, new ViewFinder(preferenceGroup));}public static void inject(Object handler, PreferenceActivity preferenceActivity) {injectObject(handler, new ViewFinder(preferenceActivity));}@SuppressWarnings("ConstantConditions")private static void injectObject(Object handler, ViewFinder finder) {Class<?> handlerType = handler.getClass();// inject ContentViewContentView contentView = handlerType.getAnnotation(ContentView.class);if (contentView != null) {try {Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);setContentViewMethod.invoke(handler, contentView.value());} catch (Throwable e) {LogUtils.e(e.getMessage(), e);}}// inject viewField[] fields = handlerType.getDeclaredFields();if (fields != null && fields.length > 0) {for (Field field : fields) {ViewInject viewInject = field.getAnnotation(ViewInject.class);if (viewInject != null) {try {View view = finder.findViewById(viewInject.value(), viewInject.parentId());if (view != null) {field.setAccessible(true);field.set(handler, view);}} catch (Throwable e) {LogUtils.e(e.getMessage(), e);}} else {ResInject resInject = field.getAnnotation(ResInject.class);if (resInject != null) {try {Object res = ResLoader.loadRes(resInject.type(), finder.getContext(), resInject.id());if (res != null) {field.setAccessible(true);field.set(handler, res);}} catch (Throwable e) {LogUtils.e(e.getMessage(), e);}} else {PreferenceInject preferenceInject = field.getAnnotation(PreferenceInject.class);if (preferenceInject != null) {try {Preference preference = finder.findPreference(preferenceInject.value());if (preference != null) {field.setAccessible(true);field.set(handler, preference);}} catch (Throwable e) {LogUtils.e(e.getMessage(), e);}}}}}}// inject eventMethod[] methods = handlerType.getDeclaredMethods();if (methods != null && methods.length > 0) {for (Method method : methods) {Annotation[] annotations = method.getDeclaredAnnotations();//便利注解目的:为了获取我们想要的注解对象if (annotations != null && annotations.length > 0) {for (Annotation annotation : annotations) {//获取注解类型Class<?> annType = annotation.annotationType();if (annType.getAnnotation(EventBase.class) != null) {method.setAccessible(true);try {// ProGuard:-keep class * extends java.lang.annotation.Annotation { *; }Method valueMethod = annType.getDeclaredMethod("value");Method parentIdMethod = null;try {parentIdMethod = annType.getDeclaredMethod("parentId");} catch (Throwable e) {}//获取OnClick、OnLongClick......注解身上的value方法//values说白了就是控件的id数组Object values = valueMethod.invoke(annotation);Object parentIds = parentIdMethod == null ? null : parentIdMethod.invoke(annotation);int parentIdsLen = parentIds == null ? 0 : Array.getLength(parentIds);//获取数组长度int len = Array.getLength(values);//遍历id数组for (int i = 0; i < len; i++) {ViewInjectInfo info = new ViewInjectInfo();//获取数组中试图的id(一个的id)info.value = Array.get(values, i);info.parentId = parentIdsLen > i ? (Integer) Array.get(parentIds, i) : 0;EventListenerManager.addEventMethod(finder, info, annotation, handler, method);}} catch (Throwable e) {LogUtils.e(e.getMessage(), e);}}}}}}}}
复制代码

绑定事件(通过动态代理实现) EventListenerManager.Java

import android.view.View;
import com.lidroid.xutils.util.LogUtils;
import com.lidroid.xutils.util.DoubleKeyValueMap;
import com.lidroid.xutils.view.annotation.event.EventBase;import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;public class EventListenerManager {private EventListenerManager() {}/*** k1: viewInjectInfo* k2: interface Type* value: listener*/private final static DoubleKeyValueMap<ViewInjectInfo, Class<?>, Object> listenerCache =new DoubleKeyValueMap<ViewInjectInfo, Class<?>, Object>();public static void addEventMethod(ViewFinder finder,ViewInjectInfo info,Annotation eventAnnotation,Object handler,Method method) {try {View view = finder.findViewByInfo(info);if (view != null) {EventBase eventBase = eventAnnotation.annotationType().getAnnotation(EventBase.class);//监听类型:OnClickListener、OnTouchListener、OnLongClickListener......Class<?> listenerType = eventBase.listenerType();//事件源(你要给那个View绑定监听,而且该监听对应的方法)//View.setOnClickListener() View.setOnTouchListener view.setOnLongClickListenerString listenerSetter = eventBase.listenerSetter();//监听方法:onClick方法、onTouch方法、onLongClick方法String methodName = eventBase.methodName();//addNewMethod该属性作用:控制是否需要创建代理对象,如果缓存存在,我们不需要创建,不存在则创建//false:代表创建 true:代表不创建boolean addNewMethod = false;//从缓存中获取提高了性能、节约了性能Object listener = listenerCache.get(info, listenerType);DynamicHandler dynamicHandler = null;if (listener != null) {dynamicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);addNewMethod = handler.equals(dynamicHandler.getHandler());if (addNewMethod) {dynamicHandler.addMethod(methodName, method);}}if (!addNewMethod) {//第一次添加监听dynamicHandler = new DynamicHandler(handler);dynamicHandler.addMethod(methodName, method);//listener:代理对象listener = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[]{listenerType},dynamicHandler);//缓存listenerCache.put(info, listenerType, listener);}//绑定监听Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);setEventListenerMethod.invoke(view, listener);}} catch (Throwable e) {LogUtils.e(e.getMessage(), e);}}//WeakReference?为什么?//第一点:及时清理内存//第二点:Activity很有可能会被意外释放(意外关闭,而这个时候你刚好执行代码到了控件的加载)//添加弱引用目的:为了防止对象意外被释放关闭而产生异常(典型:空指针异常)public static class DynamicHandler implements InvocationHandler {private WeakReference<Object> handlerRef;private final HashMap<String, Method> methodMap = new HashMap<String, Method>(1);//动态代理 持有目标对象:代表Activity或者Fragmentpublic DynamicHandler(Object handler) {this.handlerRef = new WeakReference<Object>(handler);}public void addMethod(String name, Method method) {methodMap.put(name, method);}public Object getHandler() {return handlerRef.get();}public void setHandler(Object handler) {this.handlerRef = new WeakReference<Object>(handler);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object handler = handlerRef.get();if (handler != null) {String methodName = method.getName();method = methodMap.get(methodName);//目的:确定代理需要的方法if (method != null) {return method.invoke(handler, args);}}return null;}}
}
复制代码

ViewInjectInfo类作用保存控件id类 将来我要扩展该类的属性 控制功能逻辑

public class ViewInjectInfo {public Object value;public int parentId;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof ViewInjectInfo)) return false;ViewInjectInfo that = (ViewInjectInfo) o;if (parentId != that.parentId) return false;if (value == null) return (null == that.value);return value.equals(that.value);}@Overridepublic int hashCode() {int result = value.hashCode();result = 31 * result + parentId;return result;}
}
复制代码

2.优化一下 优化第一步:设置方法访问权限:method.setAccessible(true); 允许访问 private形式 优化第二步:缓存优化

缺陷:注解类过于庞大。 框架变得越来越臃肿 第二个部分:XUtils框架3.0实现核心架构原理:整体架构做了重写 就一个模块进行分析(ViewUtils模块) 问题:我们Android有多少个监听,你就要定义多少个注解类?(XUtils2.0实现) 2.0注解类过于庞大。 框架变得越来越臃肿

            XUtils3.0之后整体架构大的改进和升级
复制代码

四大接口模块都通过简单工厂类获取,同受采用了静态内部类单例模式

package org.xutils;import android.app.Application;
import android.content.Context;import org.xutils.common.TaskController;
import org.xutils.common.task.TaskControllerImpl;
import org.xutils.db.DbManagerImpl;
import org.xutils.http.HttpManagerImpl;
import org.xutils.image.ImageManagerImpl;
import org.xutils.view.ViewInjectorImpl;import java.lang.reflect.Method;import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;/*** Created by wyouflf on 15/6/10.* 任务控制中心, http, image, db, view注入等接口的入口.* 需要在在application的onCreate中初始化: x.Ext.init(this);*/
public final class x {private x() {}public static boolean isDebug() {return Ext.debug;}public static Application app() {if (Ext.app == null) {try {// 在IDE进行布局预览时使用Class<?> renderActionClass = Class.forName("com.android.layoutlib.bridge.impl.RenderAction");Method method = renderActionClass.getDeclaredMethod("getCurrentContext");Context context = (Context) method.invoke(null);Ext.app = new MockApplication(context);} catch (Throwable ignored) {throw new RuntimeException("please invoke x.Ext.init(app) on Application#onCreate()"+ " and register your Application in manifest.");}}return Ext.app;}public static TaskController task() {return Ext.taskController;}public static HttpManager http() {if (Ext.httpManager == null) {HttpManagerImpl.registerInstance();}return Ext.httpManager;}public static ImageManager image() {if (Ext.imageManager == null) {ImageManagerImpl.registerInstance();}return Ext.imageManager;}public static ViewInjector view() {if (Ext.viewInjector == null) {ViewInjectorImpl.registerInstance();}return Ext.viewInjector;}public static DbManager getDb(DbManager.DaoConfig daoConfig) {return DbManagerImpl.getInstance(daoConfig);}//静态内部类单例模式public static class Ext {private static boolean debug;private static Application app;private static TaskController taskController;private static HttpManager httpManager;private static ImageManager imageManager;private static ViewInjector viewInjector;private Ext() {}public static void init(Application app) {TaskControllerImpl.registerInstance();if (Ext.app == null) {Ext.app = app;}}public static void setDebug(boolean debug) {Ext.debug = debug;}public static void setTaskController(TaskController taskController) {if (Ext.taskController == null) {Ext.taskController = taskController;}}public static void setHttpManager(HttpManager httpManager) {Ext.httpManager = httpManager;}public static void setImageManager(ImageManager imageManager) {Ext.imageManager = imageManager;}public static void setViewInjector(ViewInjector viewInjector) {Ext.viewInjector = viewInjector;}public static void setDefaultHostnameVerifier(HostnameVerifier hostnameVerifier) {HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);}}private static class MockApplication extends Application {public MockApplication(Context baseContext) {this.attachBaseContext(baseContext);}}
}
复制代码

ViewUtils模块为例: 第一个优化改进:整体架构(采用面向接口编程 同时采用了一些设计模式) 第二个优化改进:ViewUtils事件注解结构类进行了改进(由用户配置) 将所有注解事件进行了合并,有用户指定对应的监听 默认是OnClickListener监听 性能提高了(之前是嵌套循环)

ViewInjectorImpl.java

/** Copyright (c) 2013. wyouflf (wyouflf@gmail.com)** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0* Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package org.xutils.view;import android.app.Activity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import org.xutils.ViewInjector;
import org.xutils.common.util.LogUtil;
import org.xutils.view.annotation.ContentView;
import org.xutils.view.annotation.Event;
import org.xutils.view.annotation.ViewInject;
import org.xutils.x;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;public final class ViewInjectorImpl implements ViewInjector {private static final HashSet<Class<?>> IGNORED = new HashSet<Class<?>>();static {IGNORED.add(Object.class);IGNORED.add(Activity.class);IGNORED.add(android.app.Fragment.class);try {IGNORED.add(Class.forName("android.support.v4.app.Fragment"));IGNORED.add(Class.forName("android.support.v4.app.FragmentActivity"));} catch (Throwable ignored) {}}private static final Object lock = new Object();private static volatile ViewInjectorImpl instance;private ViewInjectorImpl() {}public static void registerInstance() {if (instance == null) {synchronized (lock) {if (instance == null) {instance = new ViewInjectorImpl();}}}x.Ext.setViewInjector(instance);}@Overridepublic void inject(View view) {injectObject(view, view.getClass(), new ViewFinder(view));}@Overridepublic void inject(Activity activity) {//获取Activity的ContentView的注解Class<?> handlerType = activity.getClass();try {ContentView contentView = findContentView(handlerType);if (contentView != null) {int viewId = contentView.value();if (viewId > 0) {Method setContentViewMethod = handlerType.getMethod("setContentView", int.class);setContentViewMethod.invoke(activity, viewId);}}} catch (Throwable ex) {LogUtil.e(ex.getMessage(), ex);}injectObject(activity, handlerType, new ViewFinder(activity));}@Overridepublic void inject(Object handler, View view) {injectObject(handler, handler.getClass(), new ViewFinder(view));}@Overridepublic View inject(Object fragment, LayoutInflater inflater, ViewGroup container) {// inject ContentViewView view = null;Class<?> handlerType = fragment.getClass();try {ContentView contentView = findContentView(handlerType);if (contentView != null) {int viewId = contentView.value();if (viewId > 0) {view = inflater.inflate(viewId, container, false);}}} catch (Throwable ex) {LogUtil.e(ex.getMessage(), ex);}// inject res & eventinjectObject(fragment, handlerType, new ViewFinder(view));return view;}/*** 从父类获取注解View*/private static ContentView findContentView(Class<?> thisCls) {if (thisCls == null || IGNORED.contains(thisCls)) {return null;}ContentView contentView = thisCls.getAnnotation(ContentView.class);if (contentView == null) {return findContentView(thisCls.getSuperclass());}return contentView;}@SuppressWarnings("ConstantConditions")private static void injectObject(Object handler, Class<?> handlerType, ViewFinder finder) {if (handlerType == null || IGNORED.contains(handlerType)) {return;}// 从父类到子类递归injectObject(handler, handlerType.getSuperclass(), finder);// inject viewField[] fields = handlerType.getDeclaredFields();if (fields != null && fields.length > 0) {for (Field field : fields) {Class<?> fieldType = field.getType();if (/* 不注入静态字段 */     Modifier.isStatic(field.getModifiers()) ||/* 不注入final字段 */    Modifier.isFinal(field.getModifiers()) ||/* 不注入基本类型字段 */  fieldType.isPrimitive() ||/* 不注入数组类型字段 */  fieldType.isArray()) {continue;}ViewInject viewInject = field.getAnnotation(ViewInject.class);if (viewInject != null) {try {View view = finder.findViewById(viewInject.value(), viewInject.parentId());if (view != null) {field.setAccessible(true);field.set(handler, view);} else {throw new RuntimeException("Invalid @ViewInject for "+ handlerType.getSimpleName() + "." + field.getName());}} catch (Throwable ex) {LogUtil.e(ex.getMessage(), ex);}}}} // end inject view// inject eventMethod[] methods = handlerType.getDeclaredMethods();if (methods != null && methods.length > 0) {for (Method method : methods) {//注意:静态方法不允许添加控件注解,私有方法允许访问,非私有方法不允许访问if (Modifier.isStatic(method.getModifiers())|| !Modifier.isPrivate(method.getModifiers())) {continue;}//检查当前方法是否是event注解的方法Event event = method.getAnnotation(Event.class);if (event != null) {try {// id参数int[] values = event.value();int[] parentIds = event.parentId();int parentIdsLen = parentIds == null ? 0 : parentIds.length;//循环所有id,生成ViewInfo并添加代理反射for (int i = 0; i < values.length; i++) {int value = values[i];if (value > 0) {ViewInfo info = new ViewInfo();info.value = value;info.parentId = parentIdsLen > i ? parentIds[i] : 0;method.setAccessible(true);EventListenerManager.addEventMethod(finder, info, event, handler, method);}}} catch (Throwable ex) {LogUtil.e(ex.getMessage(), ex);}}}} // end inject event}}
复制代码

在xUtils框架3.0之后,要求我们的方法必须是私有方法(注意:public不行) 让注解方法只属于当前类

  //注意:静态方法不允许添加控件注解,私有方法允许访问,非私有方法不允许访问if (Modifier.isStatic(method.getModifiers())|| !Modifier.isPrivate(method.getModifiers())) {continue;}复制代码
/** Copyright (c) 2013. wyouflf (wyouflf@gmail.com)** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      http://www.apache.org/licenses/LICENSE-2.0* Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package org.xutils.view;import android.text.TextUtils;
import android.view.View;import org.xutils.common.util.DoubleKeyValueMap;
import org.xutils.common.util.LogUtil;
import org.xutils.view.annotation.Event;import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;/*package*/ final class EventListenerManager {private final static long QUICK_EVENT_TIME_SPAN = 300;private final static HashSet<String> AVOID_QUICK_EVENT_SET = new HashSet<String>(2);static {AVOID_QUICK_EVENT_SET.add("onClick");AVOID_QUICK_EVENT_SET.add("onItemClick");}private EventListenerManager() {}/*** k1: viewInjectInfo* k2: interface Type* value: listener*/private final static DoubleKeyValueMap<ViewInfo, Class<?>, Object>listenerCache = new DoubleKeyValueMap<ViewInfo, Class<?>, Object>();public static void addEventMethod(//根据页面或view holder生成的ViewFinderViewFinder finder,//根据当前注解ID生成的ViewInfoViewInfo info,//注解对象Event event,//页面或view holder对象Object handler,//当前注解方法Method method) {try {View view = finder.findViewByInfo(info);if (view != null) {// 注解中定义的接口,比如Event注解默认的接口为View.OnClickListenerClass<?> listenerType = event.type();// 默认为空,注解接口对应的Set方法,比如setOnClickListener方法String listenerSetter = event.setter();if (TextUtils.isEmpty(listenerSetter)) {listenerSetter = "set" + listenerType.getSimpleName();}String methodName = event.method();boolean addNewMethod = false;/*根据View的ID和当前的接口类型获取已经缓存的接口实例对象,比如根据View.id和View.OnClickListener.class两个键获取这个View的OnClickListener对象*/Object listener = listenerCache.get(info, listenerType);DynamicHandler dynamicHandler = null;/*如果接口实例对象不为空获取接口对象对应的动态代理对象如果动态代理对象的handler和当前handler相同则为动态代理对象添加代理方法*/if (listener != null) {dynamicHandler = (DynamicHandler) Proxy.getInvocationHandler(listener);addNewMethod = handler.equals(dynamicHandler.getHandler());if (addNewMethod) {dynamicHandler.addMethod(methodName, method);}}// 如果还没有注册此代理if (!addNewMethod) {dynamicHandler = new DynamicHandler(handler);dynamicHandler.addMethod(methodName, method);// 生成的代理对象实例,比如View.OnClickListener的实例对象listener = Proxy.newProxyInstance(listenerType.getClassLoader(),new Class<?>[]{listenerType},dynamicHandler);listenerCache.put(info, listenerType, listener);}Method setEventListenerMethod = view.getClass().getMethod(listenerSetter, listenerType);setEventListenerMethod.invoke(view, listener);}} catch (Throwable ex) {LogUtil.e(ex.getMessage(), ex);}}public static class DynamicHandler implements InvocationHandler {// 存放代理对象,比如Fragment或view holderprivate WeakReference<Object> handlerRef;// 存放代理方法private final HashMap<String, Method> methodMap = new HashMap<String, Method>(1);private static long lastClickTime = 0;public DynamicHandler(Object handler) {this.handlerRef = new WeakReference<Object>(handler);}public void addMethod(String name, Method method) {methodMap.put(name, method);}public Object getHandler() {return handlerRef.get();}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object handler = handlerRef.get();if (handler != null) {String eventMethod = method.getName();if ("toString".equals(eventMethod)) {return DynamicHandler.class.getSimpleName();}method = methodMap.get(eventMethod);if (method == null && methodMap.size() == 1) {for (Map.Entry<String, Method> entry : methodMap.entrySet()) {if (TextUtils.isEmpty(entry.getKey())) {method = entry.getValue();}break;}}if (method != null) {if (AVOID_QUICK_EVENT_SET.contains(eventMethod)) {long timeSpan = System.currentTimeMillis() - lastClickTime;if (timeSpan < QUICK_EVENT_TIME_SPAN) {LogUtil.d("onClick cancelled: " + timeSpan);return null;}lastClickTime = System.currentTimeMillis();}try {return method.invoke(handler, args);} catch (Throwable ex) {throw new RuntimeException("invoke method error:" +handler.getClass().getName() + "#" + method.getName(), ex);}} else {LogUtil.w("method not impl: " + eventMethod + "(" + handler.getClass().getSimpleName() + ")");}}return null;}}
}
复制代码

简化Activity中得监听事件语句 // 注解中定义的接口,比如Event注解默认的接口为View.OnClickListener Class<?> listenerType = event.type(); // 默认为空,注解接口对应的Set方法,比如setOnClickListener方法 String listenerSetter = event.setter(); if (TextUtils.isEmpty(listenerSetter)) { listenerSetter = "set" + listenerType.getSimpleName(); } 否则 我们要在Activity中这么写

  @Event(listenerType = View.OnTouchListener.class, callbackMethod = "onTouch",listenerSetter = "setOnTouchListener",value={R.id.tv_title})private boolean touch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Toast.makeText(this, "触摸按下!", Toast.LENGTH_LONG).show();break;default:break;}return true;}
复制代码

动态代理—IOC框架相关推荐

  1. [动态代理三部曲:上] - 动态代理是如何坑掉了我4500块钱

    前言 不知道,起这个名字算不算是标题党呢?不过如果小伙伴们可以耐心看下去,因为会觉得不算标题党~ 这是一个系列文章,目的在于通过动态代理这个很基础的技术,进而深入挖掘诸如:动态生成class:Clas ...

  2. Java之代理(jdk静态代理,jdk动态代理,cglib动态代理,aop,aspectj)

    Java之代理... 1 一.         概念... 1 二.         jdk的静态代理... 1 三.         jdk动态代理... 4 四.         cglib 动态 ...

  3. Java进阶(十四)单元测试、反射、注释、动态代理

    十四.单元测试.反射.注释.动态代理 需要学会什么? 单元测试:开发好的系统中存在很多的方法,如何对这些方法的正确性进行测试. 反射:如何在程序运行时去得到Class对象,然后去获取Class中的每个 ...

  4. 支撑Java框架的基础技术:泛型,反射,动态代理,cglib

    以Spring为例要想看明白他的源码需要彻底理解Java的一些基础技术泛型,反射同时对于一些高级技术例如动态代理,cglib和字节码技术也需要掌握,下面就按章节来一一说清楚这些技术的核心部分,最后手写 ...

  5. 【IOC 控制反转】Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )

    文章目录 前言 一.创建 事件监听器 对应的 动态代理 二.动态代理 数据准备 三.动态代理 调用处理程序 四.动态代理 实例对象创建 前言 Android 依赖注入的核心就是通过反射获取 类 / 方 ...

  6. 动态代理/spring IOC/JAVA反射机制

    动态代理 代理的作用就是控制对象的访问权限: 首先我们需要写一个接口 这个就是代理接口 public interface Student { public void S1(); } 然后在写一个接口的 ...

  7. 静态代理、JDK与CGLIB动态代理、AOP+IoC原理

    静态代理.JDK与CGLIB动态代理.AOP+IoC 希望大家认真看完,感谢写这文章的大牛 目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用 ...

  8. 【Android 插件化】Hook 插件化框架 ( Hook Activity 启动流程 | AMS 启动前使用动态代理替换掉插件 Activity 类 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

  9. 【Android 插件化】Hook 插件化框架 ( Hook 技术 | 代理模式 | 静态代理 | 动态代理 )

    Android 插件化系列文章目录 [Android 插件化]插件化简介 ( 组件化与插件化 ) [Android 插件化]插件化原理 ( JVM 内存数据 | 类加载流程 ) [Android 插件 ...

最新文章

  1. pytorch神经网络之卷积层与全连接层参数的设置
  2. 设计模式-UML图简单介绍
  3. 全球及中国新式茶饮行业销售价值与经营布局渠道研究报告2022版
  4. C++ public、protected、private区别
  5. 【POJ - 2186】Popular Cows (Tarjan缩点)
  6. 更好也更快!最先进的图像去模糊算法DeblurGAN-v2
  7. Docker学习篇(一)Docker概述、安装和常用命令
  8. quartz集成到springboot_一个用来学习 spring boot 的开源项目,总共包含 57 个集成demo...
  9. JavaScript学习(六十五)—数组知识点总结
  10. AWR-比较两个阶段性能
  11. [转]_int64、long long 的区别
  12. 电力行业工程设计资质怎么办?专业类别有哪些?
  13. easyui Datagrid的deleteRow多行删除问题
  14. 北大哲学系杨立华先生
  15. Premiere Pro cc 2019 学习笔记
  16. vue报错[wds] disconnected
  17. 用PS把真人照片转素描手绘效果
  18. 下拉推荐在 Shopee Chatbot 中的探索和实践
  19. Mybatis--SqlSession对象创建过程
  20. c35是什么意思_混凝土c25、c30、c35分别代表什么意思?

热门文章

  1. 各类文件的文件头标志[转]
  2. 全球移动通信系统GSM(2G)
  3. win10系统下如何配置免安装版python(U盘版)及第三方库
  4. android 判断APP是否第一次打开
  5. Vue element 自定义表单验证(验证联系方式、邮箱、邮政编码)
  6. Microsoft Completes Acquisition of Collaboration Software Provider Groove Networks
  7. 输入身份证号和年份计算年龄
  8. 深海的诱惑:如何成为一名潜水员
  9. Mobius transform
  10. 聊天功能,实现:每增加一条消息整体往上移动,滚动查看聊天记录