传智播客-spring2.5(3)-spring的AOP

来源:互联网 发布:爱奇艺会员淘宝出租 编辑:程序博客网 时间:2024/05/29 15:12

Spring的AOP(以下内容参考了满江红译文《SpringFramework概述》):
1、spring的AOP支持的首要目标是为POJO提供J2EE支持。Spring AOP能够在应用服务器之间移植,所以没有厂商绑定的风险,它可以工作在web容器或者EJB容器中。
2、spring支持有状态的(每个执行逻辑对象用一个实例)和无状态的(所有执行逻辑只用一个实例)。
3、spring不支持字段拦截,因为字段拦截不符合封装原则,AOP应该是OOP的一个补充而不是与它冲突。
4、spring支持静态和动态切入:静态切入关注方法签名,动态切入还能考虑到被切入点的方法参数。切入点与拦截器分开定义,使得一个标准拦截器可以被用在不同应用程序和代码上下文中。
5、spring用动态代理(需要存在一个接口)或运行时CGLIB字节码生成(这使得类的代理成为可能)来实现AOP。这两种方法能在任何应用服务器中运行,也能工作在独立的环境中。
6、因为spring拦截的是实例级对象而不是类加载器级(粗粒度)的,所以可以在同一个类的不同实例上使用不同的执行逻辑,或把未拦截的对象和以拦截的对象一起使用。
7、(也许)spring AOP的常见用途是用于声明性事务管理。这构建于事务抽象之上,并且可以用任何POJO进行声明性事务管理。依靠事务策略,底层机制可以是JTA、JDBC、Hibernate或是其他任何提供事务管理的API。

注解方式实现

需要在配置文件中加入aop的命名空间和配置项(下面的红色字体,其实类似这样的配置都可以在下载包的范例中找到):
<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/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:aspectj-autoproxy/>
</beans>

示例代码(记得要先把调用的bean交给spring管理):
@Aspect
public class MyInterceptor {

//切入点表达式:execution(* cn.itcast.service..*.*(..))
//第一个*表示返回的类型,指所有类型,包括void返回类型,cn.itcast.service代表包名,包名后紧跟的两个小圆点表示该包的子包也属于拦截范围,
//圆点后面的*.*()表示包内所有的类+该类的所有方法,括号内的两个圆点表示该方法参数数目随意,没有参数,一个或多个参数都可以。
@Pointcut("execution (* cn.itcast.service.impl.PersonServiceBean.*(..))")
private void anyMethod(){ //声明一个切入点
System.out.println("anyMethod()");
}

//@Before("anyMethod()") "&& args(nameX)"表示切入点是那些带有一个String类型参数的方法
@Before("anyMethod() && args(nameX)") //定义前置通知
public void doAccessCheck(String nameX){
System.out.println("前置通知: " + nameX);
}

//@AfterReturning("anyMethod()") returning="result"定义了返回变量,引号里面的命名应该和注解方法的参数变量名一致
@AfterReturning(pointcut="anyMethod()",returning="result") //定义后置通知
public void doAfterReturning(String result){
System.out.println("后置通知: " + result);
}

@After("anyMethod()") //定义最终通知
public void doAfter(){
System.out.println("最终通知");
}

@AfterThrowing(pointcut="anyMethod()",throwing="e") //定义例外通知
public void doAfterThrowing(Exception e){
System.out.println("例外通知: " + e);
}

@Around("anyMethod()") //定义环绕通知
public Object doBesicProfiling(ProceedingJoinPoint pjp) throws Throwable{
//环绕通知内部必须执行pjp.proceed(),否则业务bean里被拦截的方法就不会执行
//使用环绕通知,上述几个通知方式都可以人工实现,也就没必要再定义上述通知方式
//if(){ //判断用户是否有权限
System.out.println("进入方法");
Object result = pjp.proceed();
System.out.println("退出方法");
//}
return result;
}
}


XML配置文件方式实现

没啥多说的,下面是示例:
<bean id="orderservice" class="cn.itcast.service.OrderServiceBean"/>
<bean id="log" class="cn.itcast.service.LogPrint"/>
<aop:config>
<aop:aspect id="myaop" ref="log">
<aop:pointcut id="mycut" expression="execution(* cn.itcast.service..*.*(..))"/>
<aop:before pointcut-ref="mycut" method="doAccessCheck"/>
<aop:after-returning pointcut-ref="mycut" method="doReturnCheck"/>
<aop:after-throwing pointcut-ref="mycut" method="doExceptionAction"/>
<aop:after pointcut-ref="mycut" method="doReleaseAction"/>
<aop:around pointcut-ref="mycut" method="doBasicProfiling"/>
</aop:aspect>
</aop:config>

原创粉丝点击