Spring AOP 基础

 

1.AOP的述语

(1)Joinpoint连接点

程序运行过程中的某一点.比如方法调用、属性访问、异常抛出

(2)Pointcut切点

需要进行增加的位置

(3)Advice增强

在不修改原有代码的前提下,为某一个对象增加新的功能

(4)Advisor(Aspect)切面

把散落在系统各处与横切关注点相关的重复代码抽取出来归整到一处形成一个模块,我们称为方面.

(5)Target目标对象

需要增加的目标类

(6)Introduction引介

特殊的Advice,为类添加一性属性和方法

(7)Weaving织入

将增加添加到目标类具体连接点的过程。有编译期织入,类装载期织入,动态代理织入三种,Spring采用动态代理织入。

(8)Proxy代理

一个类被AOP织入增强后,产出一个结果类。Spring AOP可以采用JDK动态代理和基于CGLib动态代理

2.Advice类型

spring共提供了五种类型的通知:

通知类型 接口 描述
Around 环绕增强 org.aopalliance.intercept.MethodInterceptor 拦截对目标方法调用
Before 前置增强 org.springframework.aop.MethodBeforeAdvice  在目标方法调用前调用
After  后置增强 org.springframework.aop.AfterReturningAdvice 在目标方法调用后调用
Throws 异常增强 org.springframework.aop.ThrowsAdvice 当目标方法抛出异常时调用

还有一类是引入增强,用来定义切入点的。

 

(1)前置增强MethodBeforeAdvice

package com.baobaotao.advice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class GreetingBeforeAdvice implements MethodBeforeAdvice {
	public void before(Method method, Object[] args, Object obj) throws Throwable {
		String clientName = (String)args[0];
		System.out.println("How are you!Mr."+clientName+".");
	}
}

 (2)后置增强AfterReturningAdvice

 

package com.baobaotao.advice;

import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;

public class GreetingAfterAdvice implements AfterReturningAdvice {

	public void afterReturning(Object returnObj, Method method, Object[] args,
			Object obj) throws Throwable {
		System.out.println("Please enjoy yourself!");
	}
}

 (3)环绕增强MethodInterceptor

 

package com.baobaotao.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class GreetingInterceptor implements MethodInterceptor {

	public Object invoke(MethodInvocation invocation) throws Throwable {
		Object[] args = invocation.getArguments();
		String clientName = (String)args[0];
		System.out.println("How are you!Mr."+clientName+".");
		
		Object obj = invocation.proceed();
		
		System.out.println("Please enjoy yourself!");
		
		return obj;
	}
}

 (4)异常抛出增强ThrowsAdvice

 

package com.baobaotao.advice;

import java.lang.reflect.Method;

import org.springframework.aop.ThrowsAdvice;

public class TransactionManager implements ThrowsAdvice {
	public void afterThrowing(Method method, Object[] args, Object target,
			Exception ex) throws Throwable {
		System.out.println("-----------");
		System.out.println("method:" + method.getName());
		System.out.println("抛出异常:" + ex.getMessage());
		System.out.println("成功回滚事务。");
	}
}

 (5)引介增强DelegatingIntroductionInterceptor

 

 

package com.baobaotao.introduce;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
public class ControllablePerformaceMonitor
		extends
			DelegatingIntroductionInterceptor implements Monitorable{
	private ThreadLocal<Boolean> MonitorStatusMap = new ThreadLocal<Boolean>();
	public void setMonitorActive(boolean active) {
		MonitorStatusMap.set(active);
	}
	public Object invoke(MethodInvocation mi) throws Throwable {
		Object obj = null;
		if (MonitorStatusMap.get() != null && MonitorStatusMap.get()) {
			PerformanceMonitor.begin(mi.getClass().getName() + "."
					+ mi.getMethod().getName());
			obj = super.invoke(mi);
			PerformanceMonitor.end();
		} else {
			obj = super.invoke(mi);
		}
		return obj;
	}
}

 

 

 

package com.baobaotao.introduce;

public interface Monitorable {
   void setMonitorActive(boolean active);
}

 

(6)xml配置

<?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-3.0.xsd">

	<bean id="greetingBefore" class="com.baobaotao.advice.GreetingBeforeAdvice" />
	<bean id="greetingAfter" class="com.baobaotao.advice.GreetingAfterAdvice" />
	<bean id="greetingAdvice" class="com.baobaotao.advice.GreetingBeforeAdvice" />
	<bean id="greetingAround" class="com.baobaotao.advice.GreetingInterceptor" />
	<bean id="target" class="com.baobaotao.advice.NaiveWaiter" />


	<!--1. greetingAdvice -->
	<!--
		bean id="waiter"
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="com.baobaotao.advice.Waiter" p:target-ref="target"
		p:interceptorNames="greetingAdvice"/
	-->


	<!--2. before and after advice -->
	<!--
		bean id="waiter"
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="com.baobaotao.advice.Waiter" p:target-ref="target"
		p:interceptorNames="greetingBefore,greetingAfter"/
	-->
    <!--3. around advice -->
	<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:proxyInterfaces="com.baobaotao.advice.Waiter" p:target-ref="target"
		p:interceptorNames="greetingAround" />


	<!--4. 异常抛出增强  
	<bean id="forumServiceTarget" class="com.baobaotao.advice.ForumService" />
	<bean id="transactionManager" class="com.baobaotao.advice.TransactionManager" />
	<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean"
	  p:interceptorNames="transactionManager"
	  p:target-ref="forumServiceTarget"
	  p:proxyTargetClass="true"/>
	  -->

<!--5..引介增强-->
	<bean id="pmonitor" class="com.baobaotao.introduce.ControllablePerformaceMonitor" />

	<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interfaces="com.baobaotao.introduce.Monitorable" 
		p:target-ref="forumServiceTarget"
		p:interceptorNames="pmonitor" 
		p:proxyTargetClass="true" />

</beans>

 

 3.Pointcut类型

(1)StaticMethodMatcherPointcut静态方法

      NameMatchMethodPointcut和AbstractRegexpMethodPointcut子类

(2)DynamicMethodMatcherPointcut动态方法

(3)AnnotationMatchingPointcut注解切点

(4)ExpressionPointcut表达式

(5)ControlFlowPointcut流程

(6)ComposablePointcut复合切点

 

例子

 

4.Advisor类型

(1)Advisor

一般要面,只有一个Advice

(2)PointcutAdvisor

具有切点的切面,包含Pointcut和Advice

(3)IntroductionAdvisor

引介切面.

 

5.使用例子

 

Waiter

 

package com.baobaotao.advisor;

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+"...");
	}
}

 WaiterDelegate

 

package com.baobaotao.advisor;

public class WaiterDelegate {
	private Waiter waiter;
	public void service(String clientName) {
		waiter.greetTo(clientName);
		waiter.serveTo(clientName);
	}
	public void setWaiter(Waiter waiter) {
		this.waiter = waiter;
	}
}

 

 

GreetingBeforeAdvice

package com.baobaotao.advisor;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class GreetingBeforeAdvice implements MethodBeforeAdvice {
	public void before(Method method, Object[] args, Object obj) throws Throwable {
		String clientName = (String)args[0];
		System.out.println(obj.getClass().getName()+"."+method.getName());
		System.out.println("How are you!Mr."+clientName+".");
	}
}

  

 

 

StaticMethodMatcherPointcutAdvisor

package com.baobaotao.advisor;

import java.lang.reflect.Method;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;

public class GreetingAdvisor extends StaticMethodMatcherPointcutAdvisor {

	public boolean matches(Method method, Class clazz) {
		return "greetTo".equals(method.getName());
	}	
	public ClassFilter getClassFilter(){
		return new ClassFilter(){
			public boolean matches(Class clazz){
				return Waiter.class.isAssignableFrom(clazz);
			}
		};
		
	}

}

 

 

DynamicMethodMatcherPointcut

package com.baobaotao.advisor;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.springframework.aop.ClassFilter;
import org.springframework.aop.support.DynamicMethodMatcherPointcut;

public class GreetingDynamicPointcut extends DynamicMethodMatcherPointcut {
	private static List<String> specialClientList = new ArrayList<String>();
	static {
		specialClientList.add("John");
		specialClientList.add("Tom");
	}
	public ClassFilter getClassFilter() {
		return new ClassFilter() {
			public boolean matches(Class clazz) {
				System.out.println("调用getClassFilter()对"+clazz.getName()+"做静态检查.");
				return Waiter.class.isAssignableFrom(clazz);
			}
		};
	}
//	public boolean matches(Method method, Class clazz) {
//		System.out.println("调用matches(method,clazz)对"+clazz.getName()+"."+method.getName()+"做静态检查.");
//		return "greetTo".equals(method.getName());
//	}
	public boolean matches(Method method, Class clazz, Object[] args) {
		System.out.println("调用matches(method,clazz)对"+clazz.getName()+"."+method.getName()+"做动态检查.");
		String clientName = (String) args[0];
		return specialClientList.contains(clientName);
	}

}

 Bean.xml

<?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"
	xmlns:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/util 
	http://www.springframework.org/schema/util/spring-util-3.0.xsd">

	<!-- 普通方法名匹配切面 -->
	<bean id="waiterTarget" class="com.baobaotao.advisor.Waiter" />
	<bean id="sellerTarget" class="com.baobaotao.advisor.Seller" />
	<bean id="greetingAdvice" class="com.baobaotao.advisor.GreetingBeforeAdvice" />
	<bean id="greetingAdvisor" class="com.baobaotao.advisor.GreetingAdvisor"
		p:advice-ref="greetingAdvice" />

	<bean id="parent" abstract="true"
		class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="greetingAdvisor" p:proxyTargetClass="true" />
	<bean id="waiter" parent="parent" p:target-ref="waiterTarget" />
	<bean id="seller" parent="parent" p:target-ref="sellerTarget" />
	
	
	<bean id="nameAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"
		p:advice-ref="greetingAdvice">
		<property name="mappedName">
			<value>serve*</value>
		</property>
		
	</bean>
	<bean id="waiterName" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="nameAdvisor" p:target-ref="waiterTarget"
		p:proxyTargetClass="true" />	

	<!-- 正则表达式方法名匹配切面 -->
	<bean id="regexpAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
		p:advice-ref="greetingAdvice">
		<property name="patterns">
			<list>
				<value>.*greet.*</value>
			</list>
		</property>
	</bean>
	<bean id="waiter1" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="regexpAdvisor" p:target-ref="waiterTarget"
		p:proxyTargetClass="true" />


	<!-- 动态切面 -->
	<bean id="dynamicAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
		<property name="pointcut">
			<bean class="com.baobaotao.advisor.GreetingDynamicPointcut" />
		</property>
		<property name="advice">
			<bean class="com.baobaotao.advisor.GreetingBeforeAdvice" />
		</property>
	</bean>


	<bean id="waiter2" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="dynamicAdvisor" p:target-ref="waiterTarget"
		p:proxyTargetClass="true" />

	<!-- 控制流程切面 -->
	<bean id="controlFlowPointcut" class="org.springframework.aop.support.ControlFlowPointcut">
		<constructor-arg type="java.lang.Class"
			value="com.baobaotao.advisor.WaiterDelegate" />
		<constructor-arg type="java.lang.String" value="service" />
	</bean>
	<bean id="controlFlowAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
		p:pointcut-ref="controlFlowPointcut" p:advice-ref="greetingAdvice" />
	<bean id="waiter3" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="controlFlowAdvisor" p:target-ref="waiterTarget"
		p:proxyTargetClass="true" />

	<!-- 复合切点切面 -->
	<bean id="gcp" class="com.baobaotao.advisor.GreetingComposablePointcut" />
	<bean id="composableAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"
		p:pointcut="#{gcp.intersectionPointcut}" p:advice-ref="greetingAdvice" />
	<bean id="waiter4" class="org.springframework.aop.framework.ProxyFactoryBean"
		p:interceptorNames="composableAdvisor" p:target-ref="waiterTarget"
		p:proxyTargetClass="true" />

	<!--引入切面-->
	<bean id="introduceAdvisor"
		class="org.springframework.aop.support.DefaultIntroductionAdvisor">
		<constructor-arg>
			<bean class="com.baobaotao.introduce.ControllablePerformaceMonitor" />
		</constructor-arg>
	</bean>
	<bean id="forumServiceTarget" class="com.baobaotao.introduce.ForumService" />
	<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean"
	      p:interceptorNames="introduceAdvisor"
	      p:target-ref="forumServiceTarget"
	      p:proxyTargetClass="true"/>
</beans>

 

 

 

 6.自动创建代理

(1)BeanNameAutoProxyCreator

基于Bean配置名规则的自动代理创建器

(2)DefaultAdvisorAutoProxyCreator

基于Advisor匹配机制的自动代理创建器

(3)AnnotationAwareAspectJAutoProxyCreator

基于AspectJ注解标签的自动代理创建器

<?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-3.0.xsd">
	<bean id="waiter" class="com.baobaotao.advisor.Waiter" />
	<bean id="seller" class="com.baobaotao.advisor.Seller" />
	<bean id="greetingAdvice" class="com.baobaotao.advisor.GreetingBeforeAdvice" />
	<!-- 通过Bean名称自动创建代理 -->
	<!--
		<bean
		class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
		p:beanNames="*er" p:interceptorNames="greetingAdvice"
		p:optimize="true"/>
	-->


	<!--通过Advisor自动创建代理-->
	<bean id="regexpAdvisor"
		class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
		p:patterns=".*greet.*" p:advice-ref="greetingAdvice" />
	<bean
		class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
</beans>

 

 

 

你可能感兴趣的:(Spring AOP 基础)