AOP介绍
aop这个概念不陌生了,我们就结合下边这个图来简单的介绍一下aop中的几个概念。
AOP:Aspect-Oriented Programming的缩写
JoinPoint:要切入的点,例如我们图中的addUser方法就是一个JoinPoint。
Pointcut:定系统中符合条件的一组Joinpoint。
Aspect:就是我们的切面,例如我们的日志类,里边包含了记录操作日志,记录异常日志等,那么这个对象就是一个切面。
Advice:怎么切,是在业务逻辑执行前去执行还是之后执行等。
aop实现
说了这么多,我们就以上边的图和名词解释来结合代码来讲一下他们的含义和如何执行的。
环境
业务类
一个类实现了一个接口addUser
public interface UserManager {
public void addUser(String username,String password);
}
public class UserManagerImpl implements UserManager {
@Override
public void addUser(String username, String password) {
int a = 1/0;
System.out.println("addUser");
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
注意:这里的addUser就是我们的JoinPoint,也就是切点,我们要切进去的方法。
切面(Aspect)
/**
* 定义aspect,将横切点模块化
*
* @author mengh
*
*/
public class SecurityHandler {
/**
* 操作日志
*
* @param joinPoint
*/
public void checkSecurity(JoinPoint joinPoint) {
System.out.println(joinPoint.getTarget().getClass() + "类"
+ joinPoint.getSignature().getName());
}
/**
* 异常日志
*
* @param joinPoint
*/
public void doThrowing(JoinPoint jp, Throwable ex) {
System.out.println(jp.getTarget().getClass() + "类的方法的" + jp.getSignature().getName() + "可以记录程序运行时候抛出的异常信息: " + ex.getMessage());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
注意:这里的SecurityHandler 就是我们的切面,里边包含了我们要切入的操作。
方法的参数中JoinPoint 包含了我们切入方法的各个属性,包括类,方法名,字段名等等的信息。
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<!-- 启用acpect对注解的支持 -->
<!-- <aop:aspectj-autoproxy></aop:aspectj-autoproxy> -->
<bean id="userManager" class="com.tgb.spring.UserManagerImpl" />
<bean id="securityHandler" class="com.tgb.spring.SecurityHandler" />
<aop:config>
<aop:aspect id="securityAspect" ref="securityHandler">
<!-- <aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/> -->
<!-- 操作日志的处理 -->
<aop:pointcut id="addAddMethod" expression="execution(* com.tgb.spring.*.add*(..)) ||execution(* com.tgb.spring.*.del*(..))"/>
<aop:before method="checkSecurity" pointcut-ref="addAddMethod"/>
<aop:after method="checkSecurity" pointcut-ref="addAddMethod"/>
<!-- 异常日志的处理 -->
<!-- <aop:pointcut id="addExceptionMethod" expression="execution(* com.tgb.spring.*.*(..)) || args(name)"/> -->
<aop:after-throwing method="doThrowing" pointcut="execution(* com.tgb.spring.*.add*(..))" throwing="ex"/>
</aop:aspect>
</aop:config>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
注意:代码中aop:before等就是我们说的advice,大家按照字面的意思,就是告诉spring我要怎么切,是在方法执行之前就执行还是之后等等。
aop:pointcut就是告诉spring我们要切入的规则,例如这里边就是所有添加的方法都要执行操作日志的。
method:就是对应我们的切面类的方法名称。
客户端
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");
UserManager userManager = (UserManager)beanFactory.getBean("userManager");
userManager.addUser("zhangssan", "wangwu");
}
- 1
- 2
- 3
- 4
- 5
- 6
结果
红框是我们的操作类,告诉在什么时候操作了什么类的什么方法,个人感觉这个类中实际意就是测试性能的时候大一些,但是我们蓝框中的错误处理,这样我们的程序出错了,我们也能很清晰的找到我们的程序是哪里出错了,加上时间的话,就能找到出错的时间。
但是如果我们不用呢,是不是我们的程序如果需要加一个日志的方法,就要在所有的类里边,加上错误处理,加上操作日志,这样的话,如果我们要删除这个操作日志,觉得没什么用,那么我们就要一点一点的的去删除了。