手寫Spring框架-肆
前言
前面已經(jīng)實現(xiàn)了ioc部分,本章開始來實現(xiàn)AOP內(nèi)容
AOP 意為:面向切面編程,通過預編譯的方式和運行期間動態(tài)代理實現(xiàn)程序功能功能的統(tǒng)一維護。
其實AOP也是 OOP 的延續(xù),在 Spring 框架中是一個非常重要的內(nèi)容,使用 AOP 可以對業(yè)務邏輯的各個部分進行隔離,從而使各模塊間的業(yè)務邏輯耦合度降低,提高代碼的可復用性,同時也能提高開發(fā)效率。
關(guān)于 AOP 的核心技術(shù)實現(xiàn)主要是動態(tài)代理的使用,就像你可以給一個接口的實現(xiàn)類,使用代理的方式替換掉這個實現(xiàn)類,使用代理類來處理你需要的邏輯。比如:
@Test
public void test_aop() throws NoSuchMethodException {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut("execution(* com.wtx.springframework.test.bean.UserService.*(..))");
Class<UserService> clazz = UserService.class;
Method method = clazz.getDeclaredMethod("queryUserInfo");
System.out.println(pointcut.matches(clazz));
System.out.println(pointcut.matches(method, clazz));
// true、true
}
代理類的實現(xiàn)基本都大家都見過,那么有了一個基本的思路后,接下來就需要考慮下怎么給方法做代理呢,而不是代理類。另外怎么去代理所有符合某些規(guī)則的所有類中方法呢。如果可以代理掉所有類的方法,就可以做一個方法攔截器,給所有被代理的方法添加上一些自定義處理,比如打印日志、記錄耗時、監(jiān)控異常等。
正文
定義切入點接口
用來定義哪些類或者哪些方法需要增強
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
}
定義類匹配接口
用于類層面,過濾哪些類
public interface ClassFilter {
boolean matches(Class<?> clazz);
}
定義方法匹配接口
public interface MethodMatcher {
boolean matches(Method method, Class<?> targetClass);
}
定義切點表達式
實現(xiàn)了Pointcut, ClassFilter, MethodMatcher,意味著我自己既能當切點,也能當類過濾器和方法匹配器
public class AspectJExpressionPointcut implements Pointcut, ClassFilter, MethodMatcher {
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();
private final PointcutExpression pointcutExpression;
static {
SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
}
public AspectJExpressionPointcut(String expression) {
PointcutParser pointcutParser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES, this.getClass().getClassLoader());
this.pointcutExpression = pointcutParser.parsePointcutExpression(expression);
}
@Override
public boolean matches(Class<?> clazz) {
return this.pointcutExpression.couldMatchJoinPointsInType(clazz);
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
//alwaysMatches() 就是直接返回布爾值結(jié)果:完全匹配返回 true。
return this.pointcutExpression.matchesMethodExecution(method).alwaysMatches();
}
@Override
public ClassFilter getClassFilter() {
return this;
}
@Override
public MethodMatcher getMethodMatcher() {
return this;
}
}
定義切面信息包裝類
- AdvisedSupport,主要是用于把代理、攔截、匹配的各項屬性包裝到一個類中,方便在 Proxy 實現(xiàn)類進行使用。這和你的業(yè)務開發(fā)中包裝入?yún)⑹且粋€道理
- TargetSource,是一個目標對象,在目標對象類中提供 Object 入?yún)傩裕约矮@取目標類 TargetClass 信息。
- MethodInterceptor,是一個具體攔截方法實現(xiàn)類,由用戶自己實現(xiàn) MethodInterceptor#invoke 方法,做具體的處理。像我們本文的案例中是做方法監(jiān)控處理
@Data
public class AdvisedSupport {
private TargetSource targetSource;
private MethodInterceptor methodInterceptor;
private MethodMatcher methodMatcher;
}
定義AOP代理類
定義一個標準接口,用于獲取代理類。因為具體實現(xiàn)代理的方式可以有 JDK 方式,也可以是 Cglib 方式,所以定義接口會更加方便管理實現(xiàn)類。
public interface AopProxy {
Object getProxy();
}
基于 JDK 實現(xiàn)的代理類
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
private final AdvisedSupport advisedSupport;
public JdkDynamicAopProxy(AdvisedSupport advisedSupport) {
this.advisedSupport = advisedSupport;
}
@Override
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), this.advisedSupport.getTargetSource().getTargetClass(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(this.advisedSupport.getMethodMatcher().matches(method, this.advisedSupport.getTargetSource().getTarget().getClass())){
MethodInterceptor methodInterceptor = this.advisedSupport.getMethodInterceptor();
return methodInterceptor.invoke(new ReflectiveMethodInvocation(this.advisedSupport.getTargetSource().getTarget(), method, args));
}
return method.invoke(this.advisedSupport.getTargetSource().getTarget(), args);
}
}
入?yún)⑿畔b
public class ReflectiveMethodInvocation implements MethodInvocation {
// 目標對象
protected final Object target;
// 方法
protected final Method method;
// 入?yún)? protected final Object[] arguments;
public ReflectiveMethodInvocation(Object target, Method method, Object[] arguments) {
this.target = target;
this.method = method;
this.arguments = arguments;
}
@Override
public Method getMethod() {
return this.method;
}
@Override
public Object[] getArguments() {
return this.arguments;
}
@Override
public Object proceed() throws Throwable {
return this.method.invoke(target, arguments);
}
@Override
public Object getThis() {
return this.target;
}
@Override
public AccessibleObject getStaticPart() {
return this.method;
}
}
基于Cglib實現(xiàn)的代理類
public class Cglib2AopProxy implements AopProxy{
private final AdvisedSupport advisedSupport;
public Cglib2AopProxy(AdvisedSupport advisedSupport) {
this.advisedSupport = advisedSupport;
}
@Override
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.advisedSupport.getTargetSource().getTarget().getClass());
enhancer.setInterfaces(this.advisedSupport.getTargetSource().getTargetClass());
enhancer.setCallback(new DynamicAdvisedInterceptor(this.advisedSupport));
return enhancer.create();
}
private static class DynamicAdvisedInterceptor implements MethodInterceptor {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
CglibMethodInvocation methodInvocation = new CglibMethodInvocation(advised.getTargetSource().getTarget(), method, objects, methodProxy);
if (advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) {
return advised.getMethodInterceptor().invoke(methodInvocation);
}
return methodInvocation.proceed();
}
}
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
private final MethodProxy methodProxy;
public CglibMethodInvocation(Object target, Method method, Object[] arguments, MethodProxy methodProxy) {
super(target, method, arguments);
this.methodProxy = methodProxy;
}
@Override
public Object proceed() throws Throwable {
return this.methodProxy.invoke(this.target, this.arguments);
}
}
}
基于 Cglib 使用 Enhancer 代理的類可以在運行期間為接口使用底層 ASM 字節(jié)碼增強技術(shù)處理對象的代理對象生成,因此被代理類不需要實現(xiàn)任何接口。

浙公網(wǎng)安備 33010602011771號