1. 什么是 DIP 、 IOC 、DI
依赖倒置原则 (DIP)
强调系统的 高层组件 不应当依赖于 底层组件,并且不论是高层组件还是底层组件都应该依赖于抽象。抽象不应当依赖于实现,实现应当依赖于抽象(软件设计原则)
控制反转(IOC )
一种反转流、依赖和接口的方式。就是将控制权 往高处/上层 转移,控制反转是实现依赖倒置的一种方法(DIP的具体实现方式)
依赖注入 DI
组件通过构造函数或者 set 方法,将其依赖暴露给上层,上层要设法取得组件的依赖,并将其传递给组件,依赖注入是实现控制反转的一种手段 (IOC的具体实现方式)
IOC 容器
依赖注入的框架,用来映射依赖,管理对象创建和生存周期
2. IOC 的核心是解耦
解耦的目的是: 修改耦合对象时不影响另外一个对象,降低模块之间的关联
优点:代码量少,加速开发
缺点:产生性能消耗
** 例子
public void MainActivity extends Activity{
@Inject UserInfo userInfo;
// 省略
}
反射 (Reflect)
| API | 描述 |
|---|---|
| getClass() | 获取类 |
| getAnnotation(xx.class) | 获取注解 |
| getMethod() | 获取方法 |
| invoke(xx,yy) | 执行方法 |
| getDeclaredMethods() | 获取所有方法 |
| getDeclaredFields() | 获取所有属性 |
| annotationType() | 获取注解的类型 |
注解
| @Target | 该注解用在什么上 |
|---|---|
| ElementType.TYPE | 类或接口,注解 |
| ElementType.FIELD | 属性 |
| ElementType.METHOD | 方法 |
| ElementType.PARAMETER | 参数 |
| ElementType.CONSTRUCTOR | 构造方法 |
| ElementType.LOCAL_VARIABLE | 局部的变量 |
| ElementType.ANNOTATION_TYPE | 作用于另一个注解之上 |
| ElementType.PACKAGE | 包 |
| @Retention | 该注解用在什么上 |
|---|---|
| RetentionPolicy.SOURCE | 类或接口,注解 |
| RetentionPolicy.CLASS | 编译时编译 |
| RetentionPolicy.RUNTIME | 运行时编译 |
2. 自定义注解
布局注解
* 首先创建一个注解
@Target(ElementType.TYPE) //该注解作用于类之上
@Retention(RetentionPolicy.RUNTIME) // jvm 在运行时通过反射获取注解的值
public @interface setContentView {
int value();
}
*然后是实现
private static void injectLaout(Activity activity) {
//获取类
Class<? extends Activity> claszz = activity.getClass();
//获取这个类上的注解
setContentView annotation = claszz.getAnnotation(setContentView.class);
if (annotation != null){
// 获取这个注解的值
int layoutId = annotation.value();
//执行方法: setContentView
//第一种方法
//activity.setContentView(layoutId)
//第二种方法
try {
Method method = claszz.getMethod("setContentView", int.class);
//执行方法
method.invoke(activity,layoutId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
* 使用 ,注意injectLaout 方法要在父类初始化
@setContentView(R.layout.activity_plugin)
public class PluginActivity extends PluginLibActivity {
}
控件注解
//创建注解
@Target(ElementType.FIELD) //该注解作用于s属性上
@Retention(RetentionPolicy.RUNTIME) // jvm 在运行时通过反射获取注解的值
public @interface setContentView {
int value();
}
//注解实现
private static void injectViews(Activity activity) {
//获取类
Class<? extends Activity> clazz = activity.getClass();
//获取类的所有属性
Field[] declaredFields = clazz.getDeclaredFields();
//循环 拿到每个属性
for (Field field: declaredFields){
InjectView annotation = field.getAnnotation(InjectView.class);
if (annotation !=null){
int viewId = annotation.value();
//执行方法
try {
Method method = clazz.getMethod("findViewById", int.class);
Object view = method.invoke(activity, viewId);
//将方法执行返回值view 赋值给全局某属性
field.setAccessible(true);// 设置private访问权限
field.set(activity,view);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
//使用
InjectView(R.id.btn)
Button btn;
3. 代理原理与用法
代理 (Proxy)
一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象,这样做的好处是:可以在目标对象的基础上,增强额外的功能操作,即扩展目标对象的功能
静态代理 : 从一出生就知道彼此是孪生兄弟
动态代理 : 通过动态去改变他们的关系
4. AOP 原理和拦截
面向切面编程技术,AOP基于IOC基础,是对OOP的有益补充
AOP 将应用系统分为俩部分 : 核心业务逻辑以及横向的通用逻辑
场景: 所有大中型应用都要涉及到的持久化管理(Persistemt)、事务管理(Transaction Management)、安全管理(Security)、日志管理、调试管理等...
单击和长按注解
// 创建
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventBase(listenerSetter = "setOnClickListener",listenerType = View.OnClickListener.class,callBackListener = "onClick")
public @interface OnClick {
int[] value();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@EventBase(listenerSetter = "setOnLongClickListener",listenerType = View.OnLongClickListener.class,callBackListener = "onLongClick")
public @interface OnLongClick {
int[] value();
}
//实现
private static void injectEvents(Activity activity) {
//获取类
Class<? extends Activity> clazz = activity.getClass();
//获取类的所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
// 获取每个方法的注解
Annotation[] annotations = method.getAnnotations();
//遍历每个方法的注解
for (Annotation annotation : annotations) {
//获取注解上的直接类型
Class<? extends Annotation> type = annotation.annotationType();
if (type!=null){
//通过EventBase 获取3个重要的规律
EventBase eventBase = type.getAnnotation(EventBase.class);
//事件的3个规律
String set = eventBase.listenerSetter();
String call = eventBase.callBackListener();
Class<?> atype = eventBase.listenerType();
//注解的值
try {
//通过annotationType 获取onClick 注解的value 的值
Method method1 = type.getDeclaredMethod("value");
int[] viewIds = (int[])method1.invoke(annotation);
ListenerInvocationHandler handler = new ListenerInvocationHandler(activity);
handler.addMethodMap(call,method);
//打包之后,代理处理后续工作
Proxy.newProxyInstance(atype.getClassLoader(), new Class[]{atype}, handler);
// R.id.xx
for (int viewId : viewIds) {
//控件的赋值过程
View view = activity.findViewById(viewId);
//获取方法
Method setter = view.getClass().getMethod(set,atype);
//执行
setter.invoke(view,viewId);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
// 代理类
public class ListenerInvocationHandler implements InvocationHandler {
//需要拦截的对象
private Object target;
//需要拦截的方法集合
private HashMap<String,Method> methodHashMap = new HashMap<>();
public ListenerInvocationHandler(Object target){
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (target!=null){
//获取需要拦截的方法名
String methodName = method.getName();//假如是onClick 方法
// 将拦截的方法 换成了自定义的方法
method = methodHashMap.get(methodName);//从集合中判断是否需要拦截
if (method != null){ // 找到了拦截,才执行自定义方法
if (method.getGenericParameterTypes().length == 0) return method.invoke(target);
return method.invoke(target,args);
}
}
return null;
}
/**
* 将拦截的方法加入集合
* @param methodName
* @param method
*/
public void addMethodMap(String methodName,Method method){
methodHashMap.put(methodName,method);
}
}
//使用
@onClick(R.id.xx,R.id.xx)
public void onClick(){
}










网友评论