SpringAOP浅析

coding

  • Spring AOP是由接入BeanPostProcessor后置处理器开始的,它是Spring IoC容器经常使用的一个特性,这个Bean后置处理器是一个监听器,可以监听容器触发的Bean声明周期时间。向容器注册后置处理器之后,向容器中管理的Bean就具备了接受IoC容器回调事件的能力。
  • BeanPostProcessor的使用非常简单,只需要提供一个BeanPostProcess接口的实现类
BeanPostProcessor的源码如下:

public interface BeanPostProcessor {

//在Bean的初始化之前提供回调入口

@Nullable

default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

//在Bean的初始化之后提供回调入口

@Nullable

default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

}

  • BeanPostProcessor后置处理器的调用发生在Spring IoC容器完成Bean实例对象的创建和属性的依赖注入之后,当应用程序第一次调用getBean()方法向Spring IoC容器索取指定Bean时,触发Spring IoC容器创建Bean实例对象并进行依赖注入。其实真正实现创建Bean对象并进行依赖注入的方法是AbstractAutowireCapableBeanFactory类的doCreateBean()方法。具体可以参考https://my.oschina.net/u/3943508/blog/4955342
为Bean实例对象添加BeanPostProcessor后置处理器的入口是intializeBean()方法,具体源码如下:

/**

* 对于传统定义的bean,从createBean调用,对于现有的bean实例,从initializeBean调用。

* 初始化给定的Bean实例,应用工厂回调以及init方法和Beanhou后置处理器。

*/

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)

//通过JDK的安全机制验证权限

if (System.getSecurityManager() != null) {

//实现PrivililegedAction接口的匿名内部类

AccessController.doPrivileged((PrivilegedAction<Object>) () -> {

invokeAwareMethods(beanName, bean);

return null;

}, getAccessControlContext());

}

else {

//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等

invokeAwareMethods(beanName, bean);

}

Object wrappedBean = bean;

if (mbd == null || !mbd.isSynthetic()) {

//调用BeanPostProcessor后置处理器的回调方法,在Bean初始化前做一些处理

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

}

//调用Bean的初始化方法

try {

invokeInitMethods(beanName, wrappedBean, mbd);

}

catch (Throwable ex) {

throw new BeanCreationException(

(mbd != null ? mbd.getResourceDescription() : null),

beanName, "Invocation of init method failed", ex);

}

//调用BeanPostProcessor后置处理器的回调方法,在Bean实例初始化之后做一些处理

if (mbd == null || !mbd.isSynthetic()) {

wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

}

return wrappedBean;

}

//调用BeanPostProcessor后置处理器实例初始化之前的处理方法

@Override

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

throws BeansException {

Object result = existingBean;

//遍历容器所创建的Bean添加所有的BeanPostProcessor后置处理器

for (BeanPostProcessor processor : getBeanPostProcessors()) {

//为Bean初始化之前做一些自定义的处理

Object current = processor.postProcessBeforeInitialization(result, beanName);

if (current == null) {

return result;

}

result = current;

}

return result;

}

//调用BeanPostProcessor后置处理器实例初始化之后的处理方法

@Override

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)

throws BeansException {

Object result = existingBean;

for (BeanPostProcessor processor : getBeanPostProcessors()) {

//为Bean初始化之后做一些自定义的处理

Object current = processor.postProcessAfterInitialization(result, beanName);

if (current == null) {

return result;

}

result = current;

}

return result;

}

  • BeanPostProcessor初始化前的操作方法和初始化之后的操作方法觉委派起实现子类实现。Spring中BeanPostProcessor的实现的子类非常多,分别完成不同的操作。
创建AOP代理对象

  • 创建AOP代理对象的子类AbstractAutoProxyCreator重写了PostProcessAfterInitization()方法
@Override

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {

if (bean != null) {

Object cacheKey = getCacheKey(bean.getClass(), beanName);

if (this.earlyProxyReferences.remove(cacheKey) != bean) {

return wrapIfNecessary(bean, beanName, cacheKey);

}

}

return bean;

}

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {

return bean;

}

//判断是否应该代理这个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;

}

//获取这个Bean的通知

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;

}

/**

* 为给定的Bean创建一个AOP代理。

*

* 整个过程最终是调用proxyFactory.getProxy()方法

*

* proxyFactory.getProxy()方法有两种实现方式(JDk和CGLib)

*/

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);

if (!proxyFactory.isProxyTargetClass()) {

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);

}

return proxyFactory.getProxy(getProxyClassLoader());

}

Spring 利用JDK来生成代理对象

  • 具体的代码在JdkDynamicAopProxy类中
//获取代理对象需要实现的接口

//调用Proxy.newProxyInstance() 创建代理对象

@Override

public Object getProxy(@Nullable ClassLoader classLoader) {

if (logger.isDebugEnabled()) {

logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());

}

Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

}

  • invocationHandler是JDK动态代理的核心,生成的代理对象的方法调用都会委派到invoke()方法。JdkDynamicAopProxy类也实现了这个接口。下看从invoke()方法中Spring AOP是如何织入切面的
	@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 {

// 目标对象未实现equals方法

if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {

return equals(args[0]);

}

else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {

// 目标对象未实现hashCode()方法

return hashCode();

}

else if (method.getDeclaringClass() == DecoratingProxy.class) {

return AopProxyUtils.ultimateTargetClass(this.advised);

}

//直接反射调用Advised接口或者其父类接口中定义的方法,不应该通知

else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&

method.getDeclaringClass().isAssignableFrom(Advised.class)) {

return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);

}

Object retVal;

if (this.advised.exposeProxy) {

oldProxy = AopContext.setCurrentProxy(proxy);

setProxyContext = true;

}

// 获取目标对象的类

target = targetSource.getTarget();

Class<?> targetClass = (target != null ? target.getClass() : null);

// 获取可以应用到此方法上的拦截器链

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

// 如果没有可以应用到此方法的拦截器,则直接反射调用 Method.invoke(target.args)

if (chain.isEmpty()) {

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);

}

else {

MethodInvocation invocation =

new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

retVal = invocation.proceed();

}

Class<?> returnType = method.getReturnType();

if (retVal != null && retVal == target &&

returnType != Object.class && returnType.isInstance(proxy) &&

!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {

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()) {

targetSource.releaseTarget(target);

}

if (setProxyContext) {

AopContext.setCurrentProxy(oldProxy);

}

}

}

  • 主要的实现思路为: 先获取应用到此方法上的拦截器链,如果有拦截器,则应用拦截器,并执行连接点(JoinPoint);如果没有拦截器,则直接反射执行连结点。
目标对象的增强是通过拦截器实现的

以上是 SpringAOP浅析 的全部内容, 来源链接: utcz.com/z/509855.html

回到顶部