spring源码阅读

spring的aop

bean的层级结构,这个图是从网上贴过来的↓

好吧,图没了,就这样吧,就是个bean创建时候各个类的继承实现关系图。翻一翻源码就知道了,这里就不画图了。基类是BeanFactory。

b68f2b55885ed56efc62f8e29a30d61ea01.jpg

首先是创建bean。嗯。

调用applyBeanPostProcessorsAfterInitialization

然后呢,调用postProcessBeforeInstantiation方法

然后呢,调用postProcessAfterInitialization方法,处理一下实例化之后的事情,很明确,这名字真好。

然后咧,会调用wrapIfNecessary这个判断。

然后就各种判断啦,比如:对,我们想要知道的,要不要加代理。

里面会有一行代码注释:

// Create proxy if we have advice.

这个注释真的是超棒!一眼就看见了。

接下来就是实现抽象类的方法了:getAdvicesAndAdvisorsForBean

这个啊,然后往这个方法里面走一走,会发现它调用了BeanFactoryAdvisorRetrievalHelper的findAdvisorBeans。

然后如果可以创建代理,会返回一个数组。

创建代理的方法呢,源码在这里:

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

		ProxyFactory proxyFactory = new ProxyFactory();
		// Copy our properties (proxyTargetClass etc) inherited from ProxyConfig.
		proxyFactory.copyFrom(this);

		if (!shouldProxyTargetClass(beanClass, beanName)) {
			// Must allow for introductions; can't just set interfaces to
			// the target's interfaces only.
			// ==> 这里有个类加载器
			Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
			// ==> 然后这个就放到代理工厂对象里去了
			for (Class<?> targetInterface : targetInterfaces) {
				proxyFactory.addInterface(targetInterface);
			}
		}

		// specificInterceptors 这个是 TransactionInterceptor,事务拦截器,配置文件
		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(this.proxyClassLoader);
	}

proxy的方法如下:

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

然后就会调用这个方法:

	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { // hasNoUserSuppliedProxyInterfaces确定提供的AdvisedSupport是否只指定了SpringProxy接口(或者根本没有指定代理接口)。
			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()) {
				return new JdkDynamicAopProxy(config);
			}
			if (!cglibAvailable) {
				throw new AopConfigException(
						"Cannot proxy target class because CGLIB2 is not available. " +
						"Add CGLIB to the class path or specify proxy interfaces.");
			}
			return CglibProxyFactory.createCglibProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

这两个属性都可以配置:optimize如果是true,则表示用jdk的动态代理;proxyTargetClass如果是true,则表示用jdk的动态代理。否则用Cglib代理。

嗯。这边就结束了。

然后我们看引入的aop的xsd文件中有如下配置:

	<xsd:element name="aspectj-autoproxy">
		<xsd:annotation>
			<xsd:documentation source="java:org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"><![CDATA[
	Enables the use of the @AspectJ style of Spring AOP.
			]]></xsd:documentation>
		</xsd:annotation>
		<xsd:complexType>
			<xsd:sequence>
				<xsd:element name="include" type="includeType" minOccurs="0" maxOccurs="unbounded">
					<xsd:annotation>
						<xsd:documentation><![CDATA[
	Indicates that only @AspectJ beans with names matched by the (regex)
	pattern will be considered as defining aspects to use for Spring autoproxying.
						]]></xsd:documentation>
					</xsd:annotation>
				</xsd:element>
			</xsd:sequence>
			<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
				<xsd:annotation>
					<xsd:documentation><![CDATA[
	Are class-based (CGLIB) proxies to be created? By default, standard
	Java interface-based proxies are created.
					]]></xsd:documentation>
				</xsd:annotation>
			</xsd:attribute>
			<xsd:attribute name="expose-proxy" type="xsd:boolean" default="false">
				<xsd:annotation>
					<xsd:documentation><![CDATA[
	Indicate that the proxy should be exposed by the AOP framework as a
	ThreadLocal for retrieval via the AopContext class. Off by default,
	i.e. no guarantees that AopContext access will work.
					]]></xsd:documentation>
				</xsd:annotation>
			</xsd:attribute>
		</xsd:complexType>
	</xsd:element>

表明调用的是AnnotationAwareAspectJAutoProxyCreator类。

这个类里呢有这样的方法:

	@Override
	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		super.initBeanFactory(beanFactory);
		this.aspectJAdvisorsBuilder =
				new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
	}

	@Override
	protected boolean isInfrastructureClass(Class beanClass) {
		// Previously we setProxyTargetClass(true) in the constructor, but that has too
		// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
		// aspects. I'm not entirely happy with that as there is no good reason not
		// to advise aspects, except that it causes advice invocation to go through a
		// proxy, and if the aspect implements e.g the Ordered interface it will be
		// proxied by that interface and fail at runtime as the advice method is not
		// defined on the interface. We could potentially relax the restriction about
		// not advising aspects in the future.
		// aspectJAdvisorFactory就在这里~
		return (super.isInfrastructureClass(beanClass) || this.aspectJAdvisorFactory.isAspect(beanClass));
	}

而这个类呢,AbstractAdvisorAutoProxyCreator是这个类的超类,重写了AbstractAutoProxyCreator的诸多方法。

AbstractAutoProxyCreator的postProcessBeforeInstantiation里呢,还有这个方法:createProxy

首先调用的是BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors,获取所有beanNames,然后判断class上是否有aspect注解,如果有并且方法名没有“ajc$”,说明是需要代理的。这个判断是在AbstractAspectJAdvisorFactory里,常量名字叫:AJC_MAGIC,是不是很神奇?又是一个很棒的名字。(∩_∩)

ajc$呢,是将切面编译进字节码带上的前缀,很有趣。

 

主要就是 postProcessBeforeInstantiation方法 和 postProcessAfterInitialization方法,这两个处理方法。

 

 

转载于:https://my.oschina.net/wuyizhong/blog/2992794

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值