<bean id = "customerService" class = "com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "learn" /> <property name = "url" value = "http://learn.com" /> </bean>
<bean id = "customerService" class = "com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "learn" /> <property name = "url" value = "http://learn.com" /> </bean>
<bean id = "hijackBeforeMethodBean" class = "com.learn.spring.aop.advice.HijackBeforeMethod" />
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService" /> <property name = "interceptorNames"> <list> <value>hijackBeforeMethodBean</value> </list> </property> </bean>
</beans>
用 Spring proxy 之前,必须添加 CGLIB 类库,在之前的 pom.xml 文件中,已经添加到了其中,以下是 pom.xml 依赖:
<bean id = "customerService" class = "com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobady" /> <property name = "url" value = "Nobady.com" /> </bean>
<bean id = "hijackBeforeMethodBean" class = "com.learn.spring.aop.advice.HijackBeforeMethod" /> <bean id = "hijackAfterMethodBean" class = "com.learn.spring.aop.advice.HijackAfterMethod" />
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService" /> <property name = "interceptorNames"> <list> <value>hijackAfterMethodBean</value> </list> </property> </bean>
<bean id = "customerService" class = "com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobody" /> <property name = "url" value = "Nobody.com" /> </bean>
<bean id = "hijackBeforeMethodBean" class = "com.learn.spring.aop.advice.HijackBeforeMethod" /> <bean id = "hijackAfterMethodBean" class = "com.learn.spring.aop.advice.HijackAfterMethod" /> <bean id = "hijackThrowExceptionBean" class = "com.learn.spring.aop.advice.HijackThrowExceptionMethod" />
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService" /> <property name = "interceptorNames"> <list> <value>hijackThrowExceptionBean</value> </list> </property> </bean>
<bean id = "customerService" class = "com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobody" /> <property name = "url" value = "Nobody.com" /> </bean>
<bean id = "hijackBeforeMethodBean" class = "com.learn.spring.aop.advice.HijackBeforeMethod" /> <bean id = "hijackAfterMethodBean" class = "com.learn.spring.aop.advice.HijackAfterMethod" /> <bean id = "hijackThrowExceptionBean" class = "com.learn.spring.aop.advice.HijackThrowExceptionMethod" /> <bean id = "hijackAroundMethodBean" class = "com.learn.spring.aop.advice.HijackAroundMethod" />
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService" /> <property name = "interceptorNames"> <list> <value>hijackAroundMethodBean</value> </list> </property> </bean> </beans>
<bean id = "customerPointcut" class = "org.springframework.aop.support.NameMatchMethodPointcut"> <property name = "mappedName" value = "printName" /> </bean>
<bean id = "customerService" class = "com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobody" /> <property name = "url" value = "Nobody.com" /> </bean>
<bean id = "hijackAroundMethodBean" class = "com.learn.spring.aop.advice.HijackAroundMethod" />
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService" /> <property name = "interceptorNames"> <list> <value>customerAdvisor</value> </list> </property> </bean>
<bean id = "customerPointcut" class = "org.springframework.aop.support.NameMatchMethodPointcut"> <property name = "mappedName" value = "printName" /> </bean>
<bean id = "customerAdvisor" class = "org.springframework.aop.support.DefaultPointcutAdvisor"> <property name = "pointcut" ref = "customerPointcut" /> <property name = "advice" ref = "hijackAroundMethodBean" /> </bean>
<bean id = "customerAdvisor" class = "org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name = "mappedName" value = "printName" /> <property name = "advice" ref = "hijackAroundMethodBean" /> </bean>
<bean id = "customerService" class = "com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobody" /> <property name = "url" value = "Nobody.com" /> </bean>
<bean id = "hijackAroundMethodBean" class = "com.learn.spring.aop.advice.HijackAroundMethod" />
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService" /> <property name = "interceptorNames"> <list> <value>customerAdvisor</value> </list> </property> </bean>
<bean id = "customerAdvisor" class = "org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name = "mappedName" value = "printName" /> <property name = "advice" ref = "hijackAroundMethodBean" /> </bean>
<bean id = "customerService" class = "com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobody" /> <property name = "url" value = "Nobody.com" /> </bean>
<bean id = "hijackAroundMethodBean" class = "com.learn.spring.aop.advice.HijackAroundMethod" />
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService" /> <property name = "interceptorNames"> <list> <value>customerAdvisor</value> </list> </property> </bean>
<bean id = "customerAdvisor" class = "org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name = "patterns"> <list> <value>.*URL.*</value> </list> </property> <property name = "advice" ref = "hijackAroundMethodBean" /> </bean>
这不是一个好的体验,例如,我们想让 DAO 层的所有 bean 都支持 AOP,以便写 SQL 日志,那么必须手工创建很多的 ProxyFactoryBean,这样会直接导致 xml 配置文件内容成几何级的倍增,不利于 xml 配置维护。幸运的是,Spring 有两种方法,可以为你自动创建 proxy。
<bean id = "customerService" class = " com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobody" /> <property name = "url" value = "Nobody.com" /> </bean>
<bean id = "hijackAroundMethodBean" class = " com.learn.spring.aop.advice.HijackAroundMethod" />
<bean id = "customerServiceProxy" class = "org.springframework.aop.framework.ProxyFactoryBean"> <property name = "target" ref = "customerService" /> <property name = "interceptorNames"> <list> <value>customerAdvisor</value> </list> </property> </bean>
<bean id = "customerAdvisor" class = "org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name = "mappedName" value = "printName" /> <property name = "advice" ref = " hijackAroundMethodBean " /> </bean> </beans>
<bean id = "customerService" class = " com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobody" /> <property name = "url" value = "Nobody.com" /> </bean>
<bean id = "hijackAroundMethodBean" class = " com.learn.spring.aop.advice.HijackAroundMethod" />
<bean class = "org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name = "beanNames"> <list> <value>*Service</value> </list> </property> <property name = "interceptorNames"> <list> <value>customerAdvisor</value> </list> </property> </bean>
<bean id = "customerAdvisor" class = "org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name = "mappedName" value = "printName" /> <property name = "advice" ref = "hijackAroundMethodBean" /> </bean> </beans>
以上配置中只要 bean 的 id 符合 *Service,就会自动创建 proxy,所以,可以用以下代码获得 proxy。
<bean id = "customerService" class = " com.learn.spring.aop.advice.CustomerService"> <property name = "name" value = "Nobody" /> <property name ="url" value = "Nobody.com" /> </bean>
<bean id = "hijackAroundMethodBean" class = " com.learn.spring.aop.advice.HijackAroundMethod" />
<bean id = "customerAdvisor" class = "org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name = "mappedName" value = "printName" /> <property name = "advice" ref = "hijackAroundMethodBean" /> </bean>
<bean class = "org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" /> </beans>
public void addCustomer() { System.out.println("addCustomer() is running ..."); }
public void deleteCustomer() { System.out.println("deleteCustomer() is running ..."); }
public String AddCustomerReturnValue() { System.out.println("AddCustomerReturnValue() is running ..."); return "abc"; }
public void addCustomerThrowException() throws Exception { System.out.println("addCustomerThrowException() is running ..."); throw new Exception("Generic Error"); }
public void addCustomerAround(String name) { System.out.println("addCustomerAround() is running ,args:"+name);
}
}
简单的 AspectJ,Advice 和 Pointcut 结合在一起
首先没有引入 Aspect 之前,Advice 和 Pointcut 是混在一起的,步骤如下:
创建一个 Aspect 类
配置 Spring 配置文件
由于接下来要使用 aspectj 的 jar 包,首先添加 maven 依赖。需要在 pom.xml 添加: