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

代理模式和面向切面编程

2016-06-25 19:58 316 查看
前言:从代理的角度总结Spring AOP

一、静态代理:你不知道我想做什么,我也不关心你做了什么

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

// 丢失的Shape接口
class Rectangle {
public void draw() {
System.out.println("Draw Rectangle");
}

public void erase() {
System.out.println("Erase Rectangle");
}
}

// 共同的代理逻辑
class Interceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("create Target");
Object o = proxy.invokeSuper(obj, args);
System.out.println("destroy Target");
return o;
}
}

public class CglibDemo {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Rectangle.class);
enhancer.setCallback(new Interceptor());
Rectangle proxy = (Rectangle) enhancer.create();
proxy.draw();
proxy.erase();
}
}


View Code
四、Spring AOP:面向切面的集大成者

无论是JDK的实现方式还是CGLIB的字节码技术,我们都可以利用Spring AOP做最后的统一处理。要说利用Spring AOP创建代理的唯一不足之处就是,无论被代理对象还是代理对象本身都必须交给Spring容器来管理,如果你仅仅是希望实现一个简单的代理逻辑而并不愿意大范围修改代码,引入Spring显然过于笨重。

一个简单的Service接口

package aop;

public interface Service {
void bar();
}


创建ServiceImpl类实现上述接口

package aop;

public class ServiceImpl implements Service {

@Override
public void bar() {
System.out.println("service bar");
}
}


编写ServiceB类(没有实现接口的被代理对象)

package aop;

public class ServiceB {
public void throwException(int type) {
System.out.println("service B");
if (type == 1) {
throw new IllegalArgumentException("测试异常");
}
}
}


编写功能齐备的代理逻辑

package aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class AdviceImpl {
// 方法前插入
public void doBefore(JoinPoint jp) {
System.out.println(
"log Begining method: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());
}

// 方法后插入
public void doAfter(JoinPoint jp) {
System.out.println(
"log Ending method: " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName());
}

// 前后一起插入的完整逻辑
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long time = System.currentTimeMillis();
Object retVal = pjp.proceed();
time = System.currentTimeMillis() - time;
System.out.println("process time: " + time + " ms");
return retVal;
}

// 捕获异常,相当于把被代理对象放置在try...catch中
public void doThrowing(JoinPoint jp, Throwable ex) {
System.out.println("method " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName()
+ " throw exception");
System.out.println(ex.getMessage());
}
} 


通过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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <aop:config>
<aop:aspect id="aspect" ref="aspectBean">
<aop:pointcut id="businessService" expression="execution(* aop.*.*(..))" />
<aop:before pointcut-ref="businessService" method="doBefore" />
<aop:after pointcut-ref="businessService" method="doAfter" />
<aop:around pointcut-ref="businessService" method="doAround" />
<aop:after-throwing pointcut-ref="businessService"
method="doThrowing" throwing="ex" />
</aop:aspect>
</aop:config>
<bean id="aspectBean" class="aop.AdviceImpl" />
<bean id="service" class="aop.ServiceImpl" />
<bean id="serviceB" class="aop.ServiceB" />
</beans>


通过junit演示

package aop;

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

public class AopTest {
@Test
public void aop() {
ApplicationContext ctx = new ClassPathXmlApplicationContext("aop/spring.xml");
  // 查看所有对象是否都正确的交给spring来管理
for (String beanName : ctx.getBeanDefinitionNames()) {
System.out.println(beanName);
}
System.out.println("===============伟大的分割线================");
ServiceB serviceB = (ServiceB) ctx.getBean("serviceB");
serviceB.throwException(1);
}
}


之前我曾经写过一篇博客专门总结过spring官方文档有关aop的章节,感兴趣的朋友可以自己查看。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: