环绕通知的一种实现方式就是把前两种综合起来: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <!-- 装配前置通知Bean --> <bean class="org.niit.springaop.example3.WelcomeAdvice" name="beforeWaiter"></bean> <!-- 装配后置通知Bean(通知) --> <bean class="org.niit.springaop.example3.ByeAdvice" name="afterWaiter"></bean> <!-- 装配顾客Bean(要被代理的目标对象) --> <bean class="org.niit.springaop.example3.ConsumerImpl" name="consumerTarget"> <property name="foodName" value="汉堡"></property> <property name="name" value="张先生"></property> </bean> <!-- 大多数切面是由定义切面行为的通知和定义切面在什么地方执行的切入点组合而成的。 spring认识到这一点,提供了Advisor,它把通知和切入点组合到一个对象中。 --> <!-- 顾问 --> <bean class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor" name="myAdvisor1"> <property name="advice" ref="beforeWaiter"></property> <!-- 切入点 --> <!--当被调用的方法名字与给出的映射名字匹配时,这个切入点才匹配. 你可以使用明确的方法名也可以在名字的开始或者结束处使用通配符* --> <!-- 可以有一个或者多个映射 --> <property name="mappedNames"> <list> <value>ea*</value> </list> </property> <!--一个映射如下 --> <!-- <property name="mappedName"> <value>ea*</value> </property> --> </bean> <!-- 大多数切面是由定义切面行为的通知和定义切面在什么地方执行的切入点组合而成的。 spring认识到这一点,提供了Advisor,它把通知和切入点组合到一个对象中。 --> <!-- 顾问 --> <bean class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor" name="myAdvisor2"> <property name="advice" ref="afterWaiter"></property> <!-- 切入点 --> <!--当被调用的方法名字与给出的映射名字匹配时,这个切入点才匹配. 你可以使用明确的方法名也可以在名字的开始或者结束处使用通配符* --> <!-- 可以有一个或者多个映射 --> <property name="mappedNames"> <list> <value>ea*</value> </list> </property> <!--一个映射如下 --> <!-- <property name="mappedName"> <value>ea*</value> </property> --> </bean> <!-- 创建代理Bean,我们最终关心的和使用的代理后的对象 --> <bean class="org.springframework.aop.framework.ProxyFactoryBean" name="consumer"> <!-- 被代理的目标对象【代理谁??】 --> <property name="target" ref="consumerTarget"></property> <!-- 代理类要实现的接口 --> <property name="proxyInterfaces" value="org.niit.springaop.example3.IConsumer"></property> <!-- 要织入的通知 --> <property name="interceptorNames"> <list> <value>myAdvisor1</value> <value>myAdvisor2</value> </list> </property> </bean> <!-- ProxyFactoryBean的常用属性 target 代理的目标对象 proxyInterfaces 代理应该实现的接口列表 interceptorNames 需要应用到目标对象上的通知Bean的名字,可以时拦截器、Advisor或其他通知类型的名字. singleton 在每次调用getBean时,工厂是否返回的是同一个代理类实例。 ProxyTargetClass 是否代理目标类,而不是实现接口.只能在使用CGLIB(即必须部署了CGLIB JAR包)时使用 --> </beans> 测试代码一: package org.niit.springaop.example3; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class Client1 { private static BeanFactory bf = null; private static ApplicationContext appCxt = null; private static ApplicationContext getAppCxt() { if (appCxt==null){ /*实例化ApplicationContext接口对象的多种方式*/ //appCxt = new FileSystemXmlApplicationContext("c://applicationContext.xml"); appCxt=new ClassPathXmlApplicationContext("org/niit/springaop/example3/aop.xml");; } return appCxt; } private static BeanFactory getBeanFactory() { if (bf==null){ Resource res = new ClassPathResource("org/niit/springaop/example3/aop.xml"); bf = new XmlBeanFactory(res); } return bf; } public static void main(String[] args) { Client1 c = new Client1(); IConsumer consumer = (IConsumer)c.getAppCxt().getBean("consumer"); consumer.eat(); } }