Spring2.5AOP

  Spring默认使用J2SE动态代理来作为AOP的代理。这样只有实现接口的类才能使用AOP。

  Spring也支持CGLIB代理,对于需要代理类而不是代理接口的时候,就会使用CGLIB代理。

  如果一个类实现了某个接口,并且它有额外的其他方法,那么这些接口中没有定义的方法是不能被代理的。

  如果想使用注解形式的AOP,那么需要Java 5以上版本。

  Spring 2.0使用了和AspectJ 5一样的注解,并使用AspectJ来做切入点解析和匹配。

  使用@AspectJ形式的AOP,首先要在XML文件中添加相应的aop模式,然后使用<aop:aspectj-autoproxy />启动自动代理。并且,需要添加lib/aspectj目录下的两个jar文件。

  强制使用CGLIB代理需要将<aop:config>的proxy-target-class属性设为true。使用@AspectJ风格时要想强制使用CGLIB代理,要将<aop:aspectj-autoproxy>的proxy-target-class属性设为true。

  

  声明一个切面:@Aspect。

  切面仍然需要在Spring容器中定义,即使用<bean>的方式或者注解。

  在Spring AOP中,切面类本身不可能是其他切面中通知的目标。

 

  声明一个切入点:

  一个切入点分两部分:切入点签名和切入点表达式。

  在@Aspect风格的AOP中,切入点签名通过一个普通的方法来定义,但是必须返回void,方法名就是切入点名。切入点表达式使用@Pointcut("")来表示。

 

  Spring团队建议,定义一个包含多个通用切入点的切面,可以在任何地方共享这个切面。需要注意,引用切入点需要写全限定类名.方法名形式。

  

  切入点表达式:

  Spring使用下面这些切入点指示符:

  • execution:匹配方法执行的连接点。
  • within:限定匹配特定类型的连接点。
  • this:限定匹配特定的连接点,其中bean引用是指定类型的实例。
  • target:限定匹配特定的连接点,其中目标对象是指定类型的实例。
  • args:限定匹配特定的连接点,其中参数是指定类型的实例。
  • @target:限定匹配特定的连接点,其中正执行对象的类持有指定类型的注解。
  • @within:限定匹配特定的连接点,其中连接点所在的类型已指定注解。
  • @args:限定匹配特定的连接点,其中实际传入的参数在运行时类型持有指定类型的注解。
  • @annotation:限定匹配特定的连接点,其中连接点的主题持有指定的注解。
  • bean:限定匹配特定的连接点,其中bean引用是指定名称的实例。这是Spring特有的PCD。

  execution表达式的一般形式为:execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)。

  只有返回类型模式、方法名模式和参数模式是必需的。

  • modifiers-pattern:方法的修饰符,例如public。
  • ret-type-pattern:方法的返回类型,如void,java.lang.String。
  • declaring-type-pattern:方法所在的包和类,中间用“.”连接。“..”表示任意数量的子包。*匹配任意类。
  • name-pattern:方法名。*匹配所有方法,
  • param-pattern:()匹配不接受任何参数的方法;(..)匹配接受任意数量参数的方法;(*)匹配接受一个任意类型参数的方法。

  execution举例:

  execution("* com.apress.prospring2.ch06.simple.TestBean2.*(..)"):任意返回类型 com.apress.prospring2.ch06.simple.TestBean2.任意名称任意参数数量任意参数类型。

  execution("* com.apress.prospring2.ch06..*.*(..)"):com.apress.prospring2.ch06的任意子包的任意类的任意方法的任意参数。

  两个点(..)在声明模式时,可用来表示子包。例如com..Test表示com下所有子包里的Test类;而在参数模式里时,表示任意数量和类型的参数。

  声明模式中的“*”表示类。

组合切入点表达式:切入点表达式可以使用&、||、和!来组合。

  within表达式:within(declaring-type-pattern)。  

  this表达式:this(class-name)。

  target表达式:target(class-name)。

  args表达式:args(type-pattern? (, type-pattern)*)。

  bean:为了匹配simple bean中所有方法的调用,我们可以写成bean(simple);为了匹配id或其中一个名称以Service结尾的bean中所有方法的调用,则可以写成bean(*Service)。

 

  声明通知:

  @Before("")、@AfterReturning("")、@AfterThrowing("")、@After("")、@Around("")。

  其中,切入点可以是已定义切入点的引用(例如:@Before("com.somepackage.SomeAspect.someMethod()")),也可以是新定义的切入点(例如:@Before("execution(* *(..))"))。

  @AfterReturning通知可以接收到目标方法的返回值:

  @AfterReturning(pointcut="",returning="retVal"),然后可以在通知执行的方法里增加Object retVal参数。@AfterThrowing与此类似。

  通知跟一个切入点表达式关联,否则没有意义。

  环绕通知的第一个参数必须是ProceedingJoinPoint类型。调用ProceedingJoinPoint的proceed()方法会导致后台的连接点方法执行。proceed方法也可以传入一个Object[]对象-该数组中的值将被作为方法执行时的参数。方法的调用者得到的返回值就是环绕通知的返回值。

  通知的类型:

  • 前置通知(Before):可抛出异常阻止目标方法的执行。可用于权限检查。
  • 后置通知(After returning):可获取目标方法的返回值。如果目标方法抛出异常,那么后置通知不能执行。可用于统计。
  • 异常通知(After throwing):可获取目标方法抛出的异常。只有目标方法抛出异常后才会执行。
  • 最终通知(After):总会执行。
  • 环绕通知(Around):

  通知参数:

  任何通知方法可以将第一个参数定义为org.aspectj.lang.JoinPoint类型(环绕通知的是ProceedingJoinPoint类型,它是JoinPoint的子类),JoinPoint接口提供了一系列有用的方法,比如getArgs()、getThis()、getTarget()、getSignature()。

  传递参数给通知:

  可以使用args来绑定参数。如果在一个args表达式中应该使用类型名字的地方使用一个参数名字,那么当通知执行的时候对应的参数值将会被传递进来。例如:

1 @Before("execution(* *(..)) && args(name)")
2 public void before(String name) {
3 System.out.println("before method.name is " + name);
4 }

  另一个方法是定义一个切入点,这个切入点在匹配某个连接点的时候“提供”了参数的值,然后直接从通知中访问那个命名切入点。例如:

@Pointcut("execution(* *(..)) && args(name)")
public void namedParameter(String name) {};

@Before("aop.MyAspect.namedParameter(name)")
public void before(String name) {
System.out.println("before method by pointcut.name is " + name);
}

  代理对象(this)、目标对象(target)和注解都可以使用一种类似的格式来绑定。

  通知顺序:

  在“进入”连接点时,最高优先级的通知会优先执行;在“退出”连接点时,最高优先级的通知会最后执行。

  如果未指定优先级,执行的顺序是未知的。

  可以在切面类中实现org.springframework.core.Ordered接口或者用@Order注解指定优先级。在两个切面中,Ordered.getValue()方法返回值较低的那个有更高的优先级。

 

  引入:

  引入使得一个切面可以定义被通知对象实现给定的接口,并且可以为那些对象提供具体实现。

  使用@DeclareParents注解来定义引入。

 

  上面都是基于注解的AOP,也可以使用基于模式的AOP。

 

  AOP风格的选择:

  Spring AOP和AspectJ:

  • 如果仅仅需要在Spring bean上通知执行操作,那么Spring AOP是合适的选择。
  • 如果需要通知domain对象或其他没有在Spring容器中管理的任何对象,那么需要使用AspectJ。
  • 如果想通知除方法之外的连接点,需要使用AspectJ。

  Spring AOP中使用@AspectJ还是XML:

  • XML不受Java版本限制;可以清晰的看出有哪些切面;单独修改方便。
  • XML不能完全将需求实现的地方封装到一个位置;XML表达能力有限制:仅仅支持“singleton”切面实例模型,并且不能组合命名连接点的声明。
  • @AspectJ风格支持其他的实例模型以及更丰富的连接点组合;具有将切面保持为一个模块单元的优点;能被AspecJ和Spring AOP两者理解。

  

  

转载于:https://www.cnblogs.com/hyhbg/archive/2012/03/20/2408235.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值