spring源码 - AOP原理理解

AOP使用

1.我们都知道我们在使用spring aop时需要在@configuration类上增加@EnableAspectJAutoProxy

2.然后在准备AOP类就可以对相应类的方法进行aop

@Component

@Aspect

public class MyAspect {

@Pointcut("execution(* com.my.service.*.*(..))")

public void aspect(){

System.out.println("aspect");

}

@Before("aspect()")

public void myBefore(JoinPoint joinPoint) {

System.out.println(" before "+joinPoint);

}

}

原理分析

1.首先我们看@EnableAspectJAutoProxy类代码

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Import(AspectJAutoProxyRegistrar.class)

public @interface EnableAspectJAutoProxy {

boolean proxyTargetClass() default false;

boolean exposeProxy() default false;

}

从上面的代码可以看出import了AspectJAutoProxyRegistrar这个类

2.查看AspectJAutoProxyRegistrar类代码

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

@Override

public void registerBeanDefinitions(

AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

AnnotationAttributes enableAspectJAutoProxy =

AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);

if (enableAspectJAutoProxy != null) {

if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {

AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);

}

if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {

AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);

}

}

}

}

从此代码可以看出类继承了ImportBeanDefinitionRegistrar 接口,而在@Import处理中其有一个处理过程会对类进行处理,主要是调用registerBeanDefinitions,主要利用他可以在beanfactory中注册新类的beandefinition,我们可以 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry)向以查找此代码,可以找到如下代码:

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(

BeanDefinitionRegistry registry, @Nullable Object source) {

return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);

}

发现此代码注册了AnnotationAwareAspectJAutoProxyCreator类beandefinition

3.查看AnnotationAwareAspectJAutoProxyCreator类的关系图

 

从上图中可以发现此类是beanPostProcessor的继承类,我们知道bean在实例化过程中会调用postProcessBeforeInstantiation、postProcessAfterInitialization方法,而我们这里逻辑先在postProcessBeforeInstantiation方法把有@Aspect注解类放入advisedBeans中

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {

Object cacheKey = getCacheKey(beanClass, beanName);

if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {

if (this.advisedBeans.containsKey(cacheKey)) {

return null;

}

if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {

this.advisedBeans.put(cacheKey, Boolean.FALSE);

return null;

}

}

然后通过postProcessAfterInitialization中调用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;

}

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

if (specificInterceptors != DO_NOT_PROXY) {

// advisedBeans记录了某个Bean已经进行过AOP了

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;

}

通过通调用getAdvicesAndAdvisorsForBean这方法实现某个bean是否被带有注解@Aspect类给AOP了,然后通过调用createProxy方法生成代理类JdkDynamicAopProxy

@Override

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

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了,在调用方法时只能调用此类的实现接口中的方法

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

}

然后实际调方法时主要是通过JdkDynamicAopProxy的invoke方法

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 {

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

return equals(args[0]);

}

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

return hashCode();

}

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

return AopProxyUtils.ultimateTargetClass(this.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) {

// Make invocation available if necessary.

oldProxy = AopContext.setCurrentProxy(proxy);

setProxyContext = true;

}

target = targetSource.getTarget();

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

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

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

}

// Massage return value if necessary.

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

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

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

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

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值