思路:
只需要写一个BPP,在postProcessAfterInitialization方法中,对对象进行判断,看他需不需要织入切面逻辑,如果需要,那我就根据这个对象,生成一个代理对象,然后返回这个代理对象,那么最终注入容器的,自然就是代理对象了。AOP实现,就是在 getBean(…) 的时候返回的实际上是代理类的实例。
AOP源码流程
- 创建 bean 的时候,在 bean 依赖注入之后,调用 initializeBean() 实例化。
- 实例化的时候会调用 applyBeanPostProcessorsBeforeInitialization() applyBeanPostProcessorsAfterInitialization()
- 在后置方法中,获取bean上的通知
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
- 根据通知生成代理对象。
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
- createProxy() 根据是否有接口来选择 JDK动态代理或 CGLib代理。
- 返回这个增强的代理对象,其方法调用会委派到 invoke()上。AOP就是在 invoke() 被中织入的。
- 织入(JDK动态代理为例): InvocationHandler
// Get the interception chain for this method.
// 获取这个方法上的拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
//创建invocation对象
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
invocation.proceed();//这个对象的proceed()方法
ReflectiveMethodInvocation类:
public Object proceed() throws Throwable {
InterceptorAndDynamicMethodMatcher dm = interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
//动态匹配:运行时参数是否满足匹配条件
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
//执行当前Intercetpor
return dm.interceptor.invoke(this);
}
else {
//动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
return proceed();
}
}
源码
1.AbstractAutoProxyCreator
proxyFactory.getProxy(getProxyClassLoader());
2.ProxyFactory
createAopProxy().getProxy(classLoader);
3.ProxyCreatorSupport
getAopProxyFactory().createAopProxy(this);
DefaultAopProxyFactory.createAopProxy(this); --->JdkDynamicAopProxy
4.JdkDynamicAopProxy.getProxy(classLoader);
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
记录
类就是一个切面
springAOP借助AspectJ的语法,底层使用JDK动态代理或Cglib实现
Aspect底层借助编译器实现
@Component
@AspectJ
public class Test(){
@PointCut("execution(* org.*)")
public void pointcut(){}
@After("pointcut")//通知
public void after(){}
}
连接点: joinpoint 连接点就是 execution表达式所包含的每个点
切点:一个表达式的所有的连接点组成了切点,是一组连接点。切点就像一个表,连接点就是表里的数据