1、依赖配置方式
测试方法:
public void test1() {
String filePath = System.getProperty("user.dir") + File.separator + "src/com/dmeo/aop"
+ File.separator + "spring.xml";
BeanFactory factory = new XmlBeanFactory(new FileSystemResource(filePath));
Shopping shopping = null;
System.out.println("不使用任何通知");
shopping = (Shopping) factory.getBean("shoppingImpl");
shopping.buySomething("something");
// shopping.buyAnything("anything");
System.out.println("使用前置通知");
shopping = (Shopping) factory.getBean("welcomeAdviceShop");
shopping.buySomething("type2");
shopping.buyAnything("anything");
}
spring.xml
<bean id="welcomeAdvice" class="com.dmeo.aop.WelcomeAdvice" />
<bean id="welcomeAdviceShop"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target">
<ref local="shoppingImpl" />
</property>
<!-- 以下属性没有的话不会出错,interceptorNames如果没有配置,target的方法就不会被拦截 -->
<property name="proxyInterfaces">
<value>com.dmeo.aop.Shopping</value>
</property>
<property name="interceptorNames">
<list>
<value>welcomeAdvice</value>
</list>
</property>
</bean>
2.不干涉原先的bean配置,AOP真正的强悍啊,可以用来测试,添加日志等
1).单个通知
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<bean id="customer" class="com.dmeo.aop.Customer">
<constructor-arg index="0">
<value>xh</value>
</constructor-arg>
<constructor-arg index="1">
<value>26</value>
</constructor-arg>
</bean>
<bean id="shoppingImpl" class="com.dmeo.aop.ShoppingImpl">
<property name="customer">
<ref local="customer" />
</property>
</bean>
<bean id="welcomeAdvice" class="com.dmeo.aop.WelcomeAdvice" />
<aop:config>
<aop:pointcut id="serviceOperation-before"
expression="execution(* com.dmeo.aop.*.*(..))" />
<aop:advisor pointcut-ref="serviceOperation-before"
advice-ref="welcomeAdvice" />
</aop:config>
注意前面的bean的引用以及AOP的配置。
上面的配置只能够对切面(方法)的一种行为进行拦截,比如WelcomeAdvice实现MethodBeforeAdvice,就只能在切点调用之前进行通知(前置通知)。(后置通知 AfterReturningAdvice、环绕通知 MethodInterceptor、异常通知 ThrowsAdvice)
下面给出对切面的所有行为进行拦截通知。
2).多个通知一起拦截
<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.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
default-autowire="autodetect">
<aop:config>
<aop:aspect id="TestAspect" ref="aspectBean">
<!--配置com.dmeo.aop2包下所有类或接口的所有方法-->
<aop:pointcut id="businessService"
expression="execution(* com.dmeo.aop2.*.*(..))" />
<aop:before pointcut-ref="businessService" method="doBefore" />
<aop:after pointcut-ref="businessService" method="doAfter" />
<aop:around pointcut-ref="businessService" method="doAround" />
<aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex" />
</aop:aspect>
</aop:config>
<bean id="aspectBean" class="com.dmeo.aop2.TestAspect" />
<bean id="aService" class="com.dmeo.aop2.AServiceImpl"></bean>
<bean id="bService" class="com.dmeo.aop2.BServiceImpl"></bean>
</beans>
测试类:
public static void main(String[] args) {
String filePath = "com/dmeo/aop2/spring.xml";
// 必须得用ApplicationContext
ApplicationContext factory = new ClassPathXmlApplicationContext(filePath);
aService = (AService) factory.getBean("aService");
bService = (BServiceImpl) factory.getBean("bService");
testThrow();
}
public static void testCall() {
System.out.println("Spring AOP test");
aService.fooA("test fooA");
aService.barA();
bService.fooB();
bService.barB("test barB", 0);
}
public static void testThrow() {
try {
bService.barB("call barB", 1);
} catch (IllegalArgumentException e) {
}
}
详细代码见附件~~~
重点说明:
《Spring参考手册》中定义了以下几个AOP的重要概念,结合以上代码分析如下:
<aop:config>
的 proxy-target-class
属性设为true execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
modifiers-pattern:方法的操作权限
ret-type-pattern:返回值
declaring-type-pattern:方法所在的包
name-pattern:方法名
parm-pattern:参数名
throws-pattern:异常
其中,除ret-type-pattern和name-pattern之外,其他都是可选的。上例中,execution(* com.spring.service.*.*(..))表示com.spring.service包下,返回值为任意类型;方法名任意;参数不作限制的所有方法。