8.4.5 基于注解的 零配置 方式 2. 定义Before增强处理 在一个切面类(用@Aspect修饰的类)里使用@Before来修饰一个方法时,该方法将作为Before增强处理。使用@Before修饰时,通常需要指定一个value属性值,该属性值指定一个切入点表达式,用于指定该增强处理将被织入哪些切入点。(这个切入点表达式既可以是一个已有的切入点,也可以直接定义切入点表达式)
程序示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 E:\workspace_QingLiangJiJavaEEQiYeYingYongShiZhang5 \Before  └─src \   ├─beans.xml    ├─lee \   │ └─BeanTest.java    └─org \     └─crazyit \       └─app \         ├─aspect \         │ └─AuthAspect.java          └─service \           ├─Hello.java            ├─impl \           │ ├─HelloImpl.java            │ └─WorldImpl.java            └─World.java  
 
下面的Java类里使用@Before定义了一个Before增强处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package  org.crazyit.app.aspect;import  org.aspectj.lang.annotation.Aspect;import  org.aspectj.lang.annotation.Before;@Aspect public  class  AuthAspect {               @Before("execution(* org.crazyit.app.service.impl.*.*(..))")      public  void  authority ()      {         System.out.println("模拟执行权限检查" );     } } 
 
上面程序使用@Aspect修饰了AuthAspect类,这表明该类是一个切面类,在该切面里定义了一个authority方法—这个方法本来没有任何特殊之处,但因为使用了@Before来标注该方法,这就将该方法转换成了一个Before增强处理 。 上面程序中使用@Before注解时,直接指定了切入点表达式,指定匹配org.crazyit.app.service.impl包下所有类的所有方法的执行作为切入点。 本应用在org.crazyit.app.service.impl包下定义了两个类:HelloImpl和WorldImpl,它们与前面介绍AspectJ时所用的两个业务组件类几乎相同(只是增加实现了一个接口),并使用了@Component注解进行修饰。下面是其中HelloImpl类的代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package  org.crazyit.app.service.impl;import  org.springframework.stereotype.Component;import  org.crazyit.app.service.*;@Component("hello") public  class  HelloImpl  implements  Hello {          public  void  deleteUser (Integer id)      {         System.out.println("执行Hello组件的deleteUser删除用户:"  + id);     }          public  int  addUser (String name, String pass)      {         System.out.println("执行Hello组件的addUser添加用户:"  + name);         return  20 ;     } } 
 
从上面的HelloImpl类代码来看,它是一个如此”纯净”的Java类,它丝毫不知道将被谁来进行增强,也不知道将被进行怎样的增强——但正因为HelloImpl类的这种”无知”,才是AOP的最大魅力:目标类可以被无限地增强 。 在Spring配置文件中配置自动搜索Bean组件、自动搜索切面类, Spring AOP自动对Bean组件进行增强。下面是Spring配置文件代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?xml version="1.0"  encoding="GBK" ?> <beans  xmlns ="http://www.springframework.org/schema/beans"      xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"      xmlns:context ="http://www.springframework.org/schema/context"      xmlns:aop ="http://www.springframework.org/schema/aop"      xsi:schemaLocation ="http://www.springframework.org/schema/beans       http://www.springframework.org/schema/beans/spring-beans.xsd     http://www.springframework.org/schema/context     http://www.springframework.org/schema/context/spring-context.xsd     http://www.springframework.org/schema/aop     http://www.springframework.org/schema/aop/spring-aop.xsd" >              <context:component-scan           base-package ="org.crazyit.app.service,org.crazyit.app.aspect" >         <context:include-filter  type ="annotation"               expression ="org.aspectj.lang.annotation.Aspect"  />     </context:component-scan >                <aop:aspectj-autoproxy  />  </beans > 
 
主程序非常简单,通过Spring容器获取hello和word这两个Bean,并调用了这两个Bean的业务方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package  lee;import  org.springframework.context.*;import  org.springframework.context.support.*;import  org.crazyit.app.service.*;public  class  BeanTest {     public  static  void  main (String[] args)      {                  @SuppressWarnings("resource")          ApplicationContext  ctx  =  new  ClassPathXmlApplicationContext (                 "beans.xml" );         Hello  hello  =  ctx.getBean("hello" , Hello.class);         hello.addUser("孙悟空" , "7788" );         hello.deleteUser(1 );         World  world  =  ctx.getBean("world" , World.class);         world.bar();     } } 
 
执行主程序,将在控制台中看到下所示的效果
1 2 3 4 5 6 模拟执行权限检查 执行Hello组件的addUser添加用户:孙悟空 模拟执行权限检查 执行Hello组件的deleteUser删除用户:1 模拟执行权限检查 执行World组件的bar()方法 
 
使用Before增强处理只能在目标方法执行之前织入增强,如果Before增强处理没有特殊处理,目标方法总会自动执行,如果Before处理需要阻止目标方法的执行,可通过抛出一个异常来实现。**Before增强处理执行时,目标方法还未获得执行的机会,所以Before增强处理无法访问目标方法的返回值**。