学习自:http://blog.csdn.net/innost/article/details/49387395
关于AOP和AspectJ详细使用就不多做介绍了,上面的文章都已经介绍的比较清楚了,这里就简单具几个在android中的例子~
AOP思想:
- 第一,我们要认识到OOP世界中,有些功能是横跨并嵌入众多模块里的,比如打印日志,比如统计某个模块中某些函数的执行时间等。这些功能在各个模块里分散得很厉害,可能到处都能见到。
- 第二,AOP的目标是把这些功能集中起来,放到一个统一的地方来控制和管理。如果说,OOP如果是把问题划分到单个模块的话,那么AOP就是把涉及到众多模块的某一类问题进行统一管理。比如我们可以设计两个Aspects,一个是管理某个软件中所有模块的日志输出的功能,另外一个是管理该软件中一些特殊函数调用的权限检查。
利用aspectJ我们也可以在方法执行前后 或者执行期进行一些hook~后续慢慢加使用方法。
在项目开发中我们会经常遇到在很多地方校验url是否合法的问题:
eg
public class ImageLoader {
private static final String TAG = "EvilsoulM";
public static void loadImage(String url) {
if(TextUtils.isEmpty(url)){
return;
}
}
public static void loadImage(String url, int placeholder) {
if(TextUtils.isEmpty(url)){
return;
}
}
public static void loadImage(String url, int placeholder, int errorHolder) {
if(TextUtils.isEmpty(url)){
return;
}
}
public static void loadImage(String url, int errorHolder, boolean isFade) {
if(TextUtils.isEmpty(url)){
return;
}
}
public static void loadImage(String url, boolean isFade) {
if(TextUtils.isEmpty(url)){
return;
}
}
public static void loadImage(String url, boolean isFade, int placeHolder) {
if(TextUtils.isEmpty(url)){
return;
}
}
}
如果方法数量较少还好,我们一个个加就好了,但是如果有很多种重载的方法,或者需要统一修改下判断条件就恶心了,你就得挨个去改。如果使用了aop我们就可以统一去管理url校验:
ImageLoader
public class ImageLoader {
private static final String TAG = "EvilsoulM";
public static void loadImage(String url) {
Log.d(TAG, "loadImage() called with: " + "url = [" + url + "]");
}
public static void loadImage(String url, int placeholder) {
Log.d(TAG, "loadImage() called with: " + "url = [" + url + "], placeholder = [" + placeholder + "]");
}
public static void loadImage(String url, int placeholder, int errorHolder) {
Log.d(TAG, "loadImage() called with: " + "url = [" + url + "], placeholder = [" + placeholder + "], errorHolder = [" + errorHolder + "]");
}
public static void loadImage(String url, int errorHolder, boolean isFade) {
Log.d(TAG, "loadImage() called with: " + "url = [" + url + "], errorHolder = [" + errorHolder + "], isFade = [" + isFade + "]");
}
public static void loadImage(String url, boolean isFade) {
Log.d(TAG, "loadImage() called with: " + "url = [" + url + "], isFade = [" + isFade + "]");
}
public static void loadImage(String url, boolean isFade, int placeHolder) {
Log.d(TAG, "loadImage() called with: " + "url = [" + url + "], isFade = [" + isFade + "], placeHolder = [" + placeHolder + "]");
}
}
拦截url的aspect
@Aspect
public class CheckUrlAspect {
@Pointcut("execution(* com.evilsoulm.common.Utils.ImageLoader.loadImage(String,..))")
public void loadImageEntryPoint(String imageUri) {
}
@Around(value = "loadImageEntryPoint(imageUri)")
public Object loadImageMethod(ProceedingJoinPoint joinPoint, String imageUri) throws Throwable {
LogUtils.log("call -> loadImageMethod");
if (TextUtils.isEmpty(((String) joinPoint.getArgs()[0]))) {//统一处理url是不是为空这里用的是一个比较简单的方式,默认第一个参数就是url但是url放在第2个参数就不使用了 一些高级用法后续再加
return null;//如果为空就不执行我们拦截到的方法
}
return joinPoint.proceed();//相当于执行你拦截的方法
}
}
调用
public class MainActivity extends AppCompatActivity {
private static final String URL = "api.maoyan.com";
private static final int ERROR_ID = 0x11;
private static final int PLACE_HOLDER_ID = 0x12;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
init("name->EvilsoulM");
ImageLoader.loadImage("");//传空
ImageLoader.loadImage("", ERROR_ID);//传空
ImageLoader.loadImage("", ERROR_ID, PLACE_HOLDER_ID);//传空
ImageLoader.loadImage("", ERROR_ID, true);//传空
ImageLoader.loadImage(URL, false);
ImageLoader.loadImage(URL, false, PLACE_HOLDER_ID);
}
@MethodTime
private void init(String args) {
LogUtils.log("init() called with: " + args);
}
}
日志
12-11 11:39:25.358 15900-15900/? D/EvilsoulM: init() called with: name->EvilsoulM
12-11 11:39:25.361 15900-15900/? D/EvilsoulM: call -> loadImageMethod
12-11 11:39:25.361 15900-15900/? D/EvilsoulM: call -> loadImageMethod
12-11 11:39:25.361 15900-15900/? D/EvilsoulM: call -> loadImageMethod
12-11 11:39:25.361 15900-15900/? D/EvilsoulM: call -> loadImageMethod
12-11 11:39:25.361 15900-15900/? D/EvilsoulM: call -> loadImageMethod
12-11 11:39:25.361 15900-15900/? D/EvilsoulM: loadImage() called with: url = [api.maoyan.com], isFade = [false]
12-11 11:39:25.361 15900-15900/? D/EvilsoulM: call -> loadImageMethod
12-11 11:39:25.361 15900-15900/? D/EvilsoulM: loadImage() called with: url = [api.maoyan.com], isFade = [false], placeHolder = [18]
从上面日志就能看到 我们拦截到了6次调用,但是只执行了两次url不为空的情况
当然我们也可以使用注解来判断我们方法是否需要拦截,这种方式后续再补充。
自从有了AOP,我们就可以去掉业务逻辑中显示调用安全检查的内容,使得代码归于干净,各个模块又能各司其职。而这之中千丝万缕的联系,都由AOP来连接和管理。
还有一个使用annotation 计算方法运行时间的demo~
代码:github
网友评论
求楼主回复