AOP: 面向切面编程
面向切面思想
将软件项目中公共的通用 的类形成一个切面对象, 然后将这个切面对象以配置的形式,作用到所需要的目标对象上,这样能够提升软件的结构,容易维护,不需要在每一个模块中去编写同一块功能
通用的功能:事务管理 日志记录 权限检查 session 验证
切面(aspect):一个具有公共的 通用功能的类对象
目标对象(target):被切面 作用的对象
切入点(pointcut):连接点的查询条件,指定在目标对象中 指定的那些方法是需要被作用的一批方法.
表达式匹配规则举例:
public * addUser(com.pb.entity.User):“*”表示匹配所有类型的返回值。
public void *(com.pb.entity.User):“*”表示匹配所有方法名。
public void addUser (..):“..”表示匹配所有参数个数和类型。
* com.pb.service.*.*(..):匹配com.pb.service 包下所有类的所有方法。
* com.pb.service..*( ):匹配com.pb.service 包及子包下所有类的所有方法。
连接点(JoinPoint):切入点中某个特定点(某个方法)
通知(advise): 切面功能作用的时机或者位置
前置通知:切面功能先执行 然后执行目标对象方法的功能
后置通知: 先执行切入点的方法 然后在执行切面对象方法
环绕通知:先执行一部分切面的功能 在执行目标对象的方法 然后在执行切面另外功能
异常通知:执行切入点方法的出现异常的时候
最终通知: 在finally执行切面的功能
相当于以下结构
try{
-- 环绕通知 前半部分
-- 前置通知
//调用目标对象方法(UserServiceImpl)
-- 后置通知
-- 环绕通知 后半部分
}catch(Exception e){
-- 异常通知
}finally{
-- 最终通知
}
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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.1.xsd"><!-- 创建切面对象 -->
<bean id="loggingAspect" class="aspect.LoggingAspect"></bean>
<!-- aop的配置 -->
<aop:config>
<!-- ref:指定那个bean对象是切面对象 -->
<aop:aspect ref="loggingAspect">
<!-- 配置切入点
expression:切入点表达式
id : 切入点的id
-->
expression:切入点表达式
id : 切入点的id
-->
<aop:pointcut id="myPointCut" expression="execution(public * spring.service.*.*(..))"/>(所有类的所有方法)
<aop:pointcut id="myPointCut2" expression="execution(public * spring.service.*.*(..))"/>
<!-- 配置前置通知
method: 切面类中 的方法名 (日志记录的)
pointcut-ref: 切入点id值
-->
method: 切面类中 的方法名 (日志记录的)
pointcut-ref: 切入点id值
-->
<aop:before method="beforeMethod" pointcut-ref="myPointCut"/>
<!-- 后置通知 -->
<aop:after-returning method="afterMethod" pointcut-ref="myPointCut2"/>
<!-- 环绕通知 -->
<aop:around method="arroundMethod" pointcut-ref="myPointCut2"/>
<!-- 异常通知
<aop:after-throwing method="" pointcut-ref=""/>
最终通知
<aop:after method="" pointcut-ref=""/>
-->
</aop:aspect></aop:config>
</beans>
aspect(切面)
public class LoggingAspect{
public void beforeMethod(){
}
public void afterMethod(){
}
public Object arroundMethod(ProceedingJoinPoint pjp){
Object result;
try {
result = pjp.proceed();//调用目标对象的方法(切入点方法)
return result;
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
test
public class TestAop {
@Test
public void test(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
DeptServiceImpl deptService= (DeptServiceImpl)ac.getBean("deptService");
deptService.saveDept();
}
}
aop底层用来动态代理设计模式:
UserServiceImpl: addUser()
spring通过cglib.jar动态生成一个代理类
UserServiceImpl$1234extends UserServiceImpl{
addUser(){
--前置通知功能 增强处理
new UserServiceImpl().addUser();
--后置通知功能 增强处理
}
}