程序员负责什么?
寻找可重复代码,拉出来制作成通知;
在配置文件中,声明切入点和通知间的关系。
术语生涩难懂,“翻译”过来就是在繁冗的业务代码中可能会存在大量的重复型业务代码,我们可以将这些代码抽取出来,制作成一个类,并通过CGlib动态代理或Proxy代理方式实现功能的增强。
运行阶段Spring负责什么?
时刻监控切入点方法的运行。一旦检测到切入点方法被执行,使用代理技术,动态创建目标的代理对象,根据通知类型,在对应位置加入增强代码,完善功能,最终形成一个完整的代码业务逻辑。
几个术语名词解释:
连接点:业务逻辑接口中的接口们就是连接点,他们作为事务的核心被Spring拦截,再被识别判断是否要被增强。
切入点:被拦截并被增强的业务就是切入点,说白了就是事务接口中被增强了的接口方法。
通知:被整合出来的加强方法实现类就是通知,根据执行时间不同,分为前置通知,后置通知、异常通知、环绕通知和最终通知。
这里有一个简单的通知类型判断方法,在进行代码功能加强时,会调用method.invoke(object, args)方法,在这之前的是前置通知,这之后catch块前的是后置通知,catch块中的是异常通知,finally块中的为最终通知。
/**
* 嘴业务层的四个业务
* @author Administrator
*
*/
public interface IMouth {
void drink();
void chew();
void eat();
void rap();
}
/**
* 不管是吃喝嚼还是rap都需要先张开嘴,这是必须的,所以张嘴就可以作为一个通知整合进通知类
* @author Administrator
*
*/
public class MouthImpl implements IMouth {
public void openMouth() {
System.out.println("张开嘴");
}
@Override
public void drink() {
// openMouth();
System.out.println("喝饮料");
}
@Override
public void chew() {
// openMouth();
System.out.println("嚼东西");
}
@Override
public void eat() {
// openMouth();
System.out.println("吃汉堡");
}
@Override
public void rap() {
// openMouth();
System.out.println("你看这个面他又长又宽,就像这个碗他又大又圆");
}
}
/*
* 对嘴业务的增强代码,这就是一个增强类,也叫通知类
*/
public class MouthManager {
public static void openMouth() {
System.out.println("张开嘴");
}
public static void closeMouth() {
System.out.println("合上嘴");
}
public static void cantCloseMouth() {
System.out.println("脱臼了!快去医院!");
}
public static void finallyClose() {
System.out.println("正常的合上嘴巴");
}
}
/**
* 通过CGLib代理完善业务逻辑
* @author Administrator
*
*/
public class MouthProxy {
public static IMouth getProxy() {
MouthImpl mouth = new MouthImpl();
MouthImpl mouthProxy = (MouthImpl) Enhancer.create(MouthImpl.class, new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
try {
Object rtValue = null;
MouthManager.openMouth(); //前置通知
rtValue = method.invoke(mouth, args);
MouthManager.closeMouth(); //后置通知
return rtValue;
} catch (Exception e){
MouthManager.cantCloseMouth(); // 异常通知
throw new RuntimeException(e);
} finally {
MouthManager.finallyClose(); // 最终通知
}
}
});
return mouthProxy;
}
}
public class Demo {
public static void main(String[] args) {
IMouth mouth = MouthProxy.getProxy();
mouth.eat();
System.out.println();
mouth.chew();
System.out.println();
mouth.drink();
System.out.println();
mouth.rap();
}
}