Spring AOP之切面
程序员文章站
2022-05-24 09:49:23
...
静态普通方法名匹配切面
1.定义两个业务类 服务生和售货员
public class Waiter {
public void greetTo(String name) {
System.out.println("waiter greet to " + name + "...");
}
public void serveTo(String name) {
System.out.println("waiter serving " + name + "...");
}
}
public class Seller {
public void greetTo(String name) {
System.out.println("seller greet to " + name + "...");
}
}
Seller和Waiter拥有一个相同名称的方法greetTo();
现在通过StaticMathodMatcherPointcutAdvisor定义一个切面,在Waiter类greetTo()方法调用前织入一个前置增强。
public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {
//切点方法匹配 匹配greetTo()方法
public boolean matches(Method method, Class<?> aClass) {
return "greetTo".equals(method.getName());
}
//仅匹配Waiter类及其子类
@Override
public ClassFilter getClassFilter() {
return new ClassFilter() {
public boolean matches(Class<?> clazz) {
return Waiter.class.isAssignableFrom(clazz);
}
};
}
}
StaticMathodMatcherPointcutAdvisor抽象为唯一定义的方法为matches()方法。
默认情况该切面匹配所有类,这里通过覆盖getClassFilter()方法,让他仅匹配Waiter类及其子类。
定义一个前置增强
public class GreetingBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object o) throws Throwable {
System.out.println(o.getClass().getName() + "." + method.getName());
String clientName = (String) args[0];
System.out.println("How are you ! Mr " + clientName + " .");
}
}
配置文件
<?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.xsd">
<!-- 代理对象 -->
<bean id="waiterTarget" class="com.smart.advisor.Waiter"/>
<bean id="sellerTarget" class="com.smart.advisor.Seller"/>
<!-- 前置增强 -->
<bean id="greetingBeforeAdvice" class="com.smart.advisor.GreetingBeforeAdvice"/>
<!-- 配置切面 向切面注入一个前置增强 -->
<bean id="greetingAdvisor" class="com.smart.advisor.GreetingAdvisor"
p:advice-ref="greetingBeforeAdvice"/>
<!-- 配置代理 -->
<bean id="waiterProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="greetingAdvisor"
p:target-ref="waiterTarget"
p:proxyTargetClass="true"/>
<!-- 配置代理 -->
<bean id="sellerProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="greetingAdvisor"
p:target-ref="sellerTarget"
p:proxyTargetClass="true"/>
</beans>
public class AdvisorTest {
public static void main(String[] args) {
String configPath = "beans.xml";
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(configPath);
Waiter waiterProxy = (Waiter) applicationContext.getBean("waiterProxy");
Seller sellerProxy = (Seller) applicationContext.getBean("sellerProxy");
waiterProxy.greetTo("john");
System.out.println("---------------");
waiterProxy.serveTo("john");
System.out.println("---------------");
sellerProxy.greetTo("messi");
}
}
com.smart.advisor.Waiter.greetTo
How are you ! Mr john .
waiter greet to john...
---------------
waiter serving john...
---------------
seller greet to messi...
切面只织入了Waiter类的greetTo()方法之前,Waiter类的serveTo()和Seller类的greetTo()方法都没有织入切面。
静态正则表达式匹配切面
<?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.xsd">
<!-- 代理对象 -->
<bean id="waiterTarget" class="com.smart.advisor.Waiter"/>
<bean id="sellerTarget" class="com.smart.advisor.Seller"/>
<!-- 前置增强 -->
<bean id="greetingBeforeAdvice" class="com.smart.advisor.GreetingBeforeAdvice"/>
<!-- 配置切面 向切面注入一个前置增强 -->
<bean id="greetingAdvisor" class="com.smart.advisor.GreetingAdvisor"
p:advice-ref="greetingBeforeAdvice"/>
<!--通过正则表达式定义切面 -->
<bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
p:advice-ref="greetingBeforeAdvice"
p:patterns=".*greet.*"
/>
<!-- 配置代理 -->
<bean id="waiterProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="regexpAdvisor"
p:target-ref="waiterTarget"
p:proxyTargetClass="true"
/>
<bean id="waiterProxy1" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="greetingAdvisor"
p:target-ref="waiterTarget"
p:proxyTargetClass="true"/>
<!-- 配置代理 -->
<bean id="sellerProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
p:interceptorNames="greetingAdvisor"
p:target-ref="sellerTarget"
p:proxyTargetClass="true"/>
</beans>
自动代理机制 让容器自动生成代理,Spring使用BeanPostProcessor自动完成
推荐阅读
-
Spring 5.x 源码 —Spring AOP源码—代理方法的调用与增强
-
Spring从MongoDB中下载文件之GridFS
-
yui3的AOP(面向切面编程)和OOP(面向对象编程)_YUI.Ext相关
-
spring中aop的xml配置方法实例详解
-
Spring Boot实战之逐行释义Hello World程序
-
spring boot之SpringApplication 事件监听
-
java JSP开发之Spring中Bean的使用
-
java开发之spring webflow实现上传单个文件及多个文件功能实例
-
Java开发之spring security实现基于MongoDB的认证功能
-
Spring AOP手动实现简单动态代理的代码