概述
目录
- 概念
- 配置即讲解
- 使用
- 1、根据方法名进行切入
- 2、自定义注入,需要方法引用(依计算方法执行需要时间为例)
概念
大家一般开发中都是使用面向对象编程(OOP,即ObjectOriented Programming)但当你学习了切面编程(AOP,即Aspect Oriented Programming)后你会爱上这种编程,简直太好用了,不知道的人看了你的代码都还不知道这是怎么实现的。
面向切面编程:Aspect Oriented Programming(AOP),是目前软件百开发中的一个热点,也是Spring框架中的一个重要内容。 可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
优点:利用AOP可以对业务逻辑的各个部分进行隔离,从而使得度业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
配置即讲解
直接参考这篇文章:面向切面编程AspectJ在Android埋点的实践
配置好了后,我们看下面代码:
@Aspect
public class LifeCycleAspect {
@Before("execution(* android.app.Activity.on**(..))")
public void onActivityMethodBefore(JoinPoint joinPoint) {
//方法名
String methodName = joinPoint.getSignature().getName();
//方法所在的类
String target = joinPoint.getTarget().toString();
Log.e("snow_aop", "类名:" + target + "=====方法名:" + methodName + "n");
}
@After("execution(* *.my*(..))")
public void onActivityMethodAfter(JoinPoint joinPoint) {
}
@Around("execution(* android.app.Activity.on**(..))")
public void onActivityMethodAll(ProceedingJoinPoint joinPoint) {
Log.e("snow_aop", "Around=======" + "onActivityMethodBefore:");
try {
//joinPoint.proceed()代表执行原始的方法
joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
Log.e("snow_aop", "Around=======" + "onActivityMethodAfter:");
}
}
上面代码就是一个aop切面编程代码,看代码有几点需要解释下:
1、@Aspect 在类名上需要注解代表此类是切面编程的类;
2、@Before:PointCut之前插入代码,先执行此代码逻辑;
@After:PointCut之后插入代码,执行代码结束在执行此代码逻辑;
@Around:Pointcuts之前和之后,插入代码,它包含了Before和After的全部功能;
注意:Around和After是不能同时作用在同一个方法上的,会产生重复切入的问题,导致切入失败。
3、“execution(* android.app.Activity.on**(…))”,关于它的说明直接看下图吧
4、onActivityMethodBefore等方法名是没有限制,想写什么方法就写什么方法
5、JoinPoint,这个可以获得很多被切入的方法信息,参考下面代码
@Before("execution(* *.my*(..))")
public void onActivityMethodBefore(JoinPoint joinPoint) {
//整体信息
String key = joinPoint.getSignature().toString();
//方法名
String name = joinPoint.getSignature().getName();
//方法所在的类
String target = joinPoint.getTarget().toString();
//方法在那个类多少行
String s = joinPoint.getSourceLocation().toString();
//方法中的参数,什么类型都可以,根据类型可以解析出参数的值
Object[] args = joinPoint.getArgs();
if (args != null) {
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg instanceof UserBean) {
UserBean userBean = (UserBean) arg;
Log.e(TAG, "对象参数值:" + userBean.getName() + "===" + userBean.getAge() + "n");
} else {
String strinn = String.valueOf(arg);
Log.e(TAG, "参数值strinn:" + strinn + "n");
}
}
}
Log.e(TAG, "onActivityMethodBefore:" + key + "n" + joinPoint.getThis());
}
//被切入的方法
private boolean myPrivate(String mm) {
return false;
}
public void myPublic(UserBean userBean) {
}
使用
1、根据方法名进行切入
1、注入代码
@Aspect
public class TraceAspect {
public static final String TAG = "snow_aop";
/**
* 在所有my开头的方法前执行
*
* @param joinPoint
*/
@Before("execution(* *.my*(..))")
public void onActivityMethodBefore(JoinPoint joinPoint) {
//方法名
String name = joinPoint.getSignature().getName();
//方法所在的类
String target = joinPoint.getTarget().toString();
//方法在那个类多少行
String s = joinPoint.getSourceLocation().toString();
//方法中的参数,什么类型都可以,根据类型可以解析出参数的值
Object[] args = joinPoint.getArgs();
if (args != null) {
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg instanceof UserBean) {
UserBean userBean = (UserBean) arg;
Log.e(TAG, "对象参数值:" + userBean.getName() + "===" + userBean.getAge() + "n");
} else {
String strinn = String.valueOf(arg);
Log.e(TAG, "参数值strinn:" + strinn + "n");
}
}
}
Log.e(TAG, "onActivityMethodBefore:" + key + "n" + joinPoint.getThis());
}
}
2、调用:你没看错,就是正常写法,没有任何调用,但你运行就会发现有数据打印出来了
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myPrivate("李四");
myPublic(new UserBean("张三", 19));
myNoParamsMethod();
}
private void myNoParamsMethod() {
}
private boolean myPrivate(String mm) {
return false;
}
public void myPublic(UserBean userBean) {
}
执行结果:
2、自定义注入,需要方法引用(依计算方法执行需要时间为例)
1、自定义注解类
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface DebugTimeConsuming {
}
2、自定义注解调用类
@Aspect
public class CustomAspect {
/**
* 注意此处DebugTimeConsuming是定义的注解类的路径
*/
private static final String POINTCUT_METHOD =
"execution(@com.snow.gintonic.custom.DebugTimeConsuming * *(..))";
@Pointcut(POINTCUT_METHOD)
public void methodAnnotatedWithDebugTrace() {
}
@Around("methodAnnotatedWithDebugTrace()")
public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String className = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName();
UseTimeHelper useTimeHelper = new UseTimeHelper();
//开始计时
useTimeHelper.start();
// 被注解的方法在这一行代码被执行
Object result = joinPoint.proceed();
//停止计时
useTimeHelper.stop();
//打印被监听方法的执行时间
Log.e("snow_aop", className + " --> " + methodName + " --耗时--> " + useTimeHelper.getTotalTimeMillis() + "ms");
return result;
}
}
3、调用,在方法前添加@DebugTimeConsuming即可
执行结果:
最后
以上就是粗暴星星为你收集整理的切面编程AOP在Android中该怎么使用概念配置即讲解使用的全部内容,希望文章能够帮你解决切面编程AOP在Android中该怎么使用概念配置即讲解使用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复