可能是因为我一直在做web开发的原因,一直都没觉得AOP有多大的作用,完全可以用拦截器或者过滤器代替,但是这不是不去了解它原理的理由,所以还是看看吧。
AOP的作用很简单就是方法增强,在方法的前后等等地方新增一些操作,比如打印日志或者处理异常什么的,原理也很简单就是动态代理。
代理模式应该都了解了,一个接口,两个实现,一个是原始实现A,一个是功能增强实现B,AOP就是根据A实现和配置来生成B实现,替换IOC中的A实现,从而让我们在使用中都使用增强的B实现。
使用过spring的应该都用过getBean()方法吧,替换就是在这个方法里实现的,在我们getBean的时候,不返回原始的bean,而是返回增强的bean就实现替换了。
源码
开始
如果我们用配置文件的方法来使用AOP的话,一定会使用到DefaultAdvisorAutoProxyCreator类,这个类能让所有的Advisor自动生效,不再需要其他配置:
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
所以这个类是很关键的,就从这个类开始吧,先看下这个类的继承结构:
看最左边的分支,看过IOC过程源码的应该很熟悉这个了,IOC过程中有对BeanPostProcessor接口的多次调用,用于功能扩展。
BeanPostProcessor
因为这部分和IOC的源码有很大程度的重合,就不从头开始看了,我们知道创建bean在AbstractAutoWireCapableBeanFactory#DoCreateBean方法中实现的,过程是创建实例->填充属性->初始化,在初始化的步骤里面会调用所有的BeanPostProcessor接口,所以直接看initializeBean方法吧。
- AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 调用BeanPostProcessor的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 调用一些初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// 调用BeanPostProcessor的postProcessAfterInitialization方法,这个在这里很关键,AOP就是在这里实现的
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这个方法很简单,也就是三阶段调用:before、配置的初始化方法、after,关键的还是接口方法的实现,所以我们再回到DefaultAdvisorAutoProxyCreator类中,postProcessAfterInitialization方法的实现在它的父类AbstractAutoProxyCreator中:
- AbstractAutoProcyCreator#postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 如果有必要就包裹?(环绕)
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
重点就是在wrapIfNecessary方法,wrap在这里我的理解就是AOP中增强的意思。
- AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
这个方法里的代码很简单,主要是一些判断之后就创建代理了(如果有advice,就创建代理),重点在createProxy方法里,具体创建代理的方法
- AbstractAutoProxyCreator#createProxy
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建代理工厂?
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 这里的proxyTargetClass和配置文件里的proxy-target-class有关
// 当<aop:config proxy-target-class='true' />时,会使用CGLIB来代理接口
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets (for introduction advice scenarios)
if (Proxy.isProxyClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
// 主要是这里,获取代理
return proxyFactory.getProxy(classLoader);
}
这个接口主要是创建了一个代理工厂,然后往工厂中设置了一些属性,最后通过代理工厂获取代理,看下getProxy方法吧。
- ProxyFactory#getProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
这里要先创建一个AopProxy,createAopProxy方法经过一系列调用会到DefaultAopProxyFactory#createAopProxy方法中
- DefaultAopProxyFactory#createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// imageCode?不太了解,并且这个是后面版本加进来的,这个值正常情况下肯定是false
// optimize也不太清楚,默认是false
// 所以条件就是(proxy-target-class) || (没有接口)
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
这里可以看到AOP默认是使用JDK动态代理的,只有当proxy-target-class配置成true或者没有实现接口才会使用CGLIB代理,主要是因为JDK代理是基于接口的,而CGLIB是基于继承,所以使用CGLIB时,要增强的方法不能用final修饰或者是private的。
createAopProxy方法看完了,我们知道了这里可能返回两种AopProxy,所以getProxy方法肯定有两种不同的实现,这里只看下JDK代理的实现吧,JDK动态代理是用反射实现的。
- JdkDynamicAopProxy#getProxy
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
我们知道JDK的动态代理需要实现InvocationHandler接口,然后在invoke方法中写具体实现,而在newProxyInstance方法中它的第三个参数就是一个InvocationHandle,这里传的是this,说明JdkDynamicAopProxy本身就是一个InvocationHandle,所以具体实现直接看它的invoke方法就可以了。
- JdkDynamicAopProxy#invoke
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 前面就不看了,都是一些判断,像什么equales,hashCode方法都是不能增强的
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
// 这个是返回值
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
// chain是空的就说明不需要增强,直接就调用method.invoke方法结束了代理
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
// 真正要看的就是这个分支了
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
到这里好像就结束了,只是粗略地看了一下实现AOP的源码,后续有要补充地再修改吧。