Spring源码分析-Spring AOP

AOP概念

传统的面向对象编程是自上而下的,而有时候会产生一些横切性问题,并且这些横切性问题和我们的主业务逻辑关系不大时,这些横切性问题不会影响到主业务逻辑的实现,但是会散落到代码的各个部分,导致难以维护。AOP,即面向切面编程,其可以处理这些横切性问题,AOP编程的思想就是将这些问题与主业务逻辑分开,以达到与主业务逻辑解耦的目的,使代码的重用性和开发效率更高。

AOP具有以下几个常见的应用场景:

  1. 日志记录
  2. 权限验证
  3. 效率检查
  4. 事务管理

Spring AOP

Spring AOP是AOP编程思想的一种实现方式,在Spring中,其采用了AspectJ对AOP的实现风格,使用AspectJ的注解方式来实现AOP。Spring AOP中具有如下概念和术语:

  1. 切面:通过使用@AspectJ来定义一个切面,在切面中定义具体的切入点和相关的通知。
  2. 连接点:程序执行过程中的一点,例如方法的执行或异常的处理。 在Spring AOP中,连接点始终代表方法的执行,即每一个方法都是一个连接点。
  3. 通知:通知指的是在特定的连接点处采取的操作,通知包括环绕通知,前置通知和后置通知。包括Spring在内的许多AOP框架都将通知建模为拦截器,并在连接点周围维护一连串的拦截器。
  4. 切入点:切入点连接点想对应,在某个连接点处进行相应的通知,该连接点就称为切入点,在Spring AOP中,切入点通过切入点表达式来定义。
  5. 目标对象:具有一个或多个通知的对象。 由于Spring AOP是使用运行时代理实现的,因此该对象始终是被代理的对象。
  6. AOP代理:由AOP框架创建的对象,用于实现切面相关的功能。 在Spring中,AOP代理采用JDK动态代理或CGLIB动态代理。
  7. 织入:连接切面与其他应用程序的一个过程,行成一个被通知的行为。这可以在编译时(例如,使用AspectJ编译器),加载时或在运行时完成。 Spring AOP在运行时执行编织。

Spring AOP源码分析

首先,我们可以通过注解或者XML配置的方式开启Spring AOP,在开启成功后,Spring容器会自动实例化一个AnnotationAwareAspectJAutoProxyCreator对象,用于实现AOP,该对象是一个BeanPostProcessor。读者可以试一下,不开启Spring AOP的话是不会实例化这个BeanPostProcessor的。
在这里插入图片描述
既然我们知道了Spring AOP是由AnnotationAwareAspectJAutoProxyCreator这个BeanPostProcessor来实现的,那了解Spring IOC的读者就知道,在Spring初始化时,在最后会对相关的Bean进行初始化,在初始化时候会调用BeanPostProcessor的相关方法,初始化方法实现如下:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged(new PrivilegedAction<Object>() {
			@Override
			public Object run() {
				invokeAwareMethods(beanName, bean);
				return null;
			}
		}, getAccessControlContext());
	}
	else {
		// 调用相关的Aware方法
		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()方法
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}

在初始化方法里面会首先调用相应的Aware方法;然后调用所有BeanPostProcessor的postProcessBeforeInitialization()方法;若该bean实现了InitializingBean接口,则会调用相应的afterPropertiesSet()方法;接着会调用所有BeanPostProcessor的postProcessAfterInitialization()方法,而Spring的AOP就是在该方法中实现的。下面看AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization()方法具体实现。

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (!this.earlyProxyReferences.contains(cacheKey)) {
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

该方法首先判断该bean之前是否被代理过,若未被代理过,则进行相应的代理,也就是调用wrapIfNecessary()方法,该方法的实现如下:

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	if (beanName != null && 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;
	}

	// 如果该bean配置了相关的advisor,即相关的advise和pointcut,则创建相关的代理对象
	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是否需要被代理,如果需要的话,则调用createProx()方法创建代理对象,具体实现如下:

protected Object createProxy(
			Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

	//首先创建代理工厂实例,用于后续创建代理对象
	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);
	for (Advisor advisor : advisors) {
		proxyFactory.addAdvisor(advisor);
	}

	proxyFactory.setTargetSource(targetSource);
	customizeProxyFactory(proxyFactory);

	proxyFactory.setFrozen(this.freezeProxy);
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}
	// 获取代理对象
	return proxyFactory.getProxy(getProxyClassLoader());
}

ProxyFactory的getProxy方法的具体实现如下:

public Object getProxy(ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}

上述方首先创建一个AopProxy对象,用于产生最终得到相关的代理对象。其中createAopProxy()方法的具体实现如下:

protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	return getAopProxyFactory().createAopProxy(this);
}

首先通过getAopProxyFactory()方法获取AOP代理工厂,然后通过所获取的AOP代理工厂创建AOP代理,具体实现如下:

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (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的动态代理,一种是使用Cglib的动态代理方式,该方法通过判断目标类是否存在接口,以及外部是否强制使用cglib代理等条件来判断最终使用哪种代理方式。
在获得具体的AopProxy对象之后,就可以获取具体的代理对象了,其中Jdk的动态代理对象中的getProxy()方法实现如下:

public Object getProxy(ClassLoader classLoader) {
	if (logger.isDebugEnabled()) {
		logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
	}
	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

熟悉Jdk动态代理的读者看到这就知道了,最终通过roxy.newProxyInstance(classLoader, proxiedInterfaces, this);来获取最终的代理对象。

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值