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
增强处理无法访问目标方法的返回值**。