您的位置:首页 > 编程语言 > Java开发

spring学习历程---AOP基础

2016-11-20 12:21 323 查看

1.前置增强

Writer.java

public interface Waiter {
void greetTo(String name);
void serveTo(String name);
}


NativeWriter.java

public class NaiveWaiter implements Waiter {

public void greetTo(String name) {
System.out.println("greet to "+name+"...");
}

public void serveTo(String name){
System.out.println("serving "+name+"...");
}
}


GreetingBeforeAdvice.java

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

import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class TestBeforeAdvice {
public static void main(String[] args) {
Waiter target = new NaiveWaiter();
BeforeAdvice  advice = new GreetingBeforeAdvice();
ProxyFactory pf = new ProxyFactory();
pf.setInterfaces(target.getClass().getInterfaces());
pf.setOptimize(true);
pf.setTarget(target);
pf.addAdvice(advice);

Waiter proxy = (Waiter)pf.getProxy();
proxy.greetTo("John");
proxy.serveTo("Tom");
}
}
beans.xml

<bean id="greetingBefore" class="com.baobaotao.advice.GreetingBeforeAdvice" />
<bean id="target" class="com.baobaotao.advice.NaiveWaiter" />

<bean id="waiter"
class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.baobaotao.advice.Waiter" p:target-ref="target"
p:interceptorNames="greetingAdvice"/>
驱动类这样写就要使用beans.xml

public static void main(String[] args) {
String configPath = "com/baobaotao/advice/beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter)ctx.getBean("waiter");
waiter.greetTo("John");
}


但测试类这样写就不必配置beans.xml

import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;

public class TestBeforeAdvice {
public static void main(String[] args) {
Waiter target = new NaiveWaiter();
BeforeAdvice  advice = new GreetingBeforeAdvice();
ProxyFactory pf = new ProxyFactory();
pf.setInterfaces(target.getClass().getInterfaces());
pf.setOptimize(true);
pf.setTarget(target);
pf.addAdvice(advice);

Waiter proxy = (Waiter)pf.getProxy();
proxy.greetTo("John");
proxy.serveTo("Tom");
}
}

2.前置增强与后置增强

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!");
}
}
beans.xml

<bean id="greetingAfter" class="com.baobaotao.advice.GreetingAfterAdvice" />
<bean id="waiter"
class="org.springframework.aop.framework.ProxyFactoryBean"
p:proxyInterfaces="com.baobaotao.advice.Waiter" p:target-ref="target"
p:interceptorNames="greetingBefore,greetingAfter"/>

3.环绕增强

它结合了前置增强与后置增强

GreetingInterceptor.java

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;
}
}
beans.xml

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

4.异常抛出增强

ForumService.java

public class ForumService {
public void removeForum(int forumId) {
// do sth...
throw new RuntimeException("运行异常。");
}
public void updateForum(Forum forum) throws Exception{
// do sth...
throw new SQLException("数据更新操作异常。");

}
}
TractionManager.java

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("成功回滚事务。");
}
}
ThrowsAdvice异常抛出增强接口没有定义方法,他只是一个标识接口,在运行期Spring使用反射的机制自行判断,我们必须采用以下签名形式定义异常抛出的增强方法:

void afterThrowing([Method method,Object[]args,Object target] , Throwable) ;

方法名必须为afterThrowing , 方法入参规定如下:前三个入参Method method,Object [] args ,Object target 是可选的(或者提供三个入参,或者不提供),而最后一个入参是Throwable或其子类。如:

afterThrowing(SQLException e);

afterThrowing(Method method,Object[]args , Object target ,RuntimeException e);

可以在同一个异常抛出增强中定义多个afterThrowing() , 当目标类方法抛出异常时,Spring会自动选择最匹配的增强方法。

beans.xml这样配置

<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.引介增强

引介增强:比较特殊,不是在目标方法周围织入增强,而是为目标类增加新的方法和属性,属于类级别而非方法级别。

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


增强代码:

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;
}

}
xml配置

<bean id="pmonitor" class="com.baobaotao.introduce.ControllablePerformaceMonitor" />
<bean id="forumServiceTarget" class="com.baobaotao.introduce.ForumService" />
<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" />
lt;/beans>
调用代码:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestIntroduce {
public static void main(String[] args) {
String configPath = "com/baobaotao/introduce/beans.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
ForumService forumService = (ForumService)ctx.getBean("forumService");
forumService.removeForum(10);
forumService.removeTopic(1022);

Monitorable moniterable = (Monitorable)forumService;   //监控开启
moniterable.setMonitorActive(true);
forumService.removeForum(10);
forumService.removeTopic(1022);
}
}

引介增强与之前的四类增强有较大区别,首先需要指定引介增强所实现的接口Monitorable;其次只能通过为目标类创建子类的方式生成代理,必须将p:proxyTargetClass设置成"true"

可以直观理解为下图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息