Spring读源码系列之AOP--03---aop底层基础类学习

Posted 大忽悠爱忽悠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring读源码系列之AOP--03---aop底层基础类学习相关的知识,希望对你有一定的参考价值。

Spring读源码系列之AOP--03---aop底层基础类学习


引子

就像IOC底层的实现依靠的是BeanWrapper,Convert,PropertyEditor这些基础设施类一样,AOP的实现底层也依赖了这样一批基础类,下面我们来看看。


Spring AOP常用类解释


AopInfrastructureBean—免被AOP代理的标记接口

AopInfrastructureBean是一个标记接口。若Bean实现了此接口,表明它是一个Spring AOP的基础类,那么这个类是不会被AOP给代理的,即使它能被切面切进去~~~

public interface AopInfrastructureBean 



ProxyConfig—AOP配置类

用于创建代理的配置的父类,以确保所有代理创建者具有一致的属性。 它有五个属性,解释如下:

public class ProxyConfig implements Serializable 

	// 标记是否直接对目标类进行代理,而不是通过接口产生代理
	private boolean proxyTargetClass = false;
	// 标记是否对代理进行优化。true:那么在生成代理对象之后,如果对代理配置进行了修改,已经创建的代理对象也不会获取修改之后的代理配置。
	// 如果exposeProxy设置为true,即使optimize为true也会被忽略。
	private boolean optimize = false;
	// 标记是否需要阻止通过该配置创建的代理对象转换为Advised类型,默认值为false,表示代理对象可以被转换为Advised类型
	//Advised接口其实就代表了被代理的对象(此接口是Spring AOP提供,它提供了方法可以对代理进行操作,比如移除一个切面之类的),它持有了代理对象的一些属性,通过它可以对生成的代理对象的一些属性进行人为干预
	// 默认情况,我们可以这么完 Advised target = (Advised) context.getBean("opaqueTest"); 从而就可以对该代理持有的一些属性进行干预勒   若此值为true,就不能这么玩了
	boolean opaque = false;
	//标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。
	//当一个代理对象需要调用它【自己】的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
	//实践场景:如何让被代理的方法在代理对象被代理的方法中被调用时,依旧能被拦截
	boolean exposeProxy = false;
	//标记是否需要冻结代理对象,即在代理对象生成之后,是否允许对其进行修改,默认为false.
	// 当我们不希望调用方修改转换成Advised对象之后的代理对象时,就可以设置为true 给冻结上即可
	private boolean frozen = false;
	...


ProxyProcessorSupport—代理创建器的通用实现

简单的说它就是提供为代理创建器提供了一些公共方法实现:

具有代理处理器通用功能的基类,特别是 ClassLoader 管理和 evaluateProxyInterfaces 算法。

@SuppressWarnings("serial")
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, BeanClassLoaderAware, AopInfrastructureBean 

	/**
AOP的自动代理创建器必须在所有的别的processors之后执行,以确保它可以代理到所有的小伙伴们,即使需要双重代理得那种
	 */
	private int order = Ordered.LOWEST_PRECEDENCE;
    
    //代理类的类加载器
	@Nullable
	private ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();
    
    //代理类的类加载器是否被手动配置了---即用户是否手动指定了类加载器
	private boolean classLoaderConfigured = false;


	/**
Set the ordering which will apply to this processor's implementation of Ordered, 
used when applying multiple processors.

The default value is Ordered.LOWEST_PRECEDENCE, meaning non-ordered.
	 */
	public void setOrder(int order) 
		this.order = order;
	

	@Override
	public int getOrder() 
		return this.order;
	

	/**
手动设置代理类加载器
	 */
	public void setProxyClassLoader(@Nullable ClassLoader classLoader) 
		this.proxyClassLoader = classLoader;
		//如果不为空,说明手动设置生效,打个标记
		this.classLoaderConfigured = (classLoader != null);
	
	
	@Nullable
	protected ClassLoader getProxyClassLoader() 
		return this.proxyClassLoader;
	
//因为继承了BeanClassLoaderAware,因此默认的代理类加载器就是beanFactory用来加载所有bean的beanClassLoader
	@Override
	public void setBeanClassLoader(ClassLoader classLoader) 
	//手动配置的优先级更高,无法覆盖
		if (!this.classLoaderConfigured) 
			this.proxyClassLoader = classLoader;
		
	


	/**
	 * Check the interfaces on the given bean class and apply them to the link ProxyFactory
	 * if appropriate.
	 * 检查给定类上的所有接口,然后检查分析决定代理方式
	 */
	protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) 
	//拿到目标类上的所有接口
		Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
		//是否存在合理的接口---可以决定是否采用jdk动态代理,如果为false则走cglib动态代理
		boolean hasReasonableProxyInterface = false;
		for (Class<?> ifc : targetInterfaces) 
			if (
              //pass内部的回调接口
              !isConfigurationCallbackInterface(ifc) && 
               //pass内部语言接口
               !isInternalLanguageInterface(ifc) &&
					//当前接口内是否存在方法
					ifc.getMethods().length > 0) 
				hasReasonableProxyInterface = true;
				break;
			
		
		//如果存在合理的接口
		if (hasReasonableProxyInterface) 
			// Must allow for introductions; can't just set interfaces to the target's interfaces only.
			// 这里Spring的Doc特别强调了:不能值只把合理的接口设置进去,而是都得加入进去
			for (Class<?> ifc : targetInterfaces) 
				proxyFactory.addInterface(ifc);
			
		
		else 
		// 这个很明显设置true,表示使用CGLIB得方式去创建代理了~~~~
		//proxyFactory继承了proxyConfig,这里调用的是proxyConfig的setProxyTargetClass方法
			proxyFactory.setProxyTargetClass(true);
		
	

	/**
判断此接口类型是否属于:容器去回调的类型,这里例举处理一些接口 初始化、销毁、自动刷新、自动关闭、Aware感知等等
	 */
	protected boolean isConfigurationCallbackInterface(Class<?> ifc) 
		return (InitializingBean.class == ifc || DisposableBean.class == ifc || Closeable.class == ifc ||
				AutoCloseable.class == ifc || ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
	

	/**
	是否是如下通用的接口。若实现的是这些接口也会排除,不认为它是实现了接口的类
	 */
	protected boolean isInternalLanguageInterface(Class<?> ifc) 
		return (ifc.getName().equals("groovy.lang.GroovyObject") ||
				ifc.getName().endsWith(".cglib.proxy.Factory") ||
				ifc.getName().endsWith(".bytebuddy.MockAccess"));
	




TargetClassAware—提供获取被代理类的接口

/**
用于在代理后面公开目标类的最小接口。
由 AOP 代理对象和代理工厂(通过 org.springframework.aop.framework.Advised)以及 TargetSources 实现。
 */
public interface TargetClassAware 

	@Nullable
	Class<?> getTargetClass();



Advised—代理类配置信息封装

Spring官方英文注释:

  • Interface to be implemented by classes that hold the configuration of a factory of AOP proxies. This configuration includes the Interceptors and other advice, Advisors, and the proxied interfaces.
  • Any AOP proxy obtained from Spring can be cast to this interface to allow manipulation of its AOP advice.

简单解释:

该接口用于保存一个代理的相关配置。比如保存了这个代理相关的拦截器、通知、增强器等等。

所有的代理对象都实现了该接口(我们就能够通过一个代理对象获取这个代理对象怎么被代理出来的相关信息)

不管是JDKproxy,还是cglib proxy,代理出来的对象都实现了org.springframework.aop.framework.Advised接口;


/**
 * Interface to be implemented by classes that hold the configuration
 * of a factory of AOP proxies. This configuration includes the
 * Interceptors and other advice, Advisors, and the proxied interfaces.
 *
 * <p>Any AOP proxy obtained from Spring can be cast to this interface to
 * allow manipulation of its AOP advice.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 13.03.2003
 * @see org.springframework.aop.framework.AdvisedSupport
 */
public interface Advised extends TargetClassAware 

	/**
	 * Return whether the Advised configuration is frozen,
	 * in which case no advice changes can be made.
	 */
	boolean isFrozen();

	/**
	 * Are we proxying the full target class instead of specified interfaces?
	 */
	boolean isProxyTargetClass();

	/**
	 * Return the interfaces proxied by the AOP proxy.
	 * <p>Will not include the target class, which may also be proxied.
	 */
	Class<?>[] getProxiedInterfaces();

	/**
	 * Determine whether the given interface is proxied.
	 */
	boolean isInterfaceProxied(Class<?> intf);

	/**
Change the TargetSource used by this Advised object.
Only works if the configuration isn't frozen.
	 */
	void setTargetSource(TargetSource targetSource);

	/**
	 * Return the @code TargetSource used by this @code Advised object.
	 */
	TargetSource getTargetSource();

	/**
设置代理是否应由 AOP 框架公开为 ThreadLocal 以通过 AopContext 类进行获取

It can be necessary to expose the proxy if an advised object needs to 
invoke a method on itself with advice applied. Otherwise, 
if an advised object invokes a method on this, no advice will be applied.
Default is false, for optimal performance.
	 */
	void setExposeProxy(boolean exposeProxy);

	/**
	 * Return whether the factory should expose the proxy as a ThreadLocal.
	 * It can be necessary to expose the proxy if an advised object needs
	 * to invoke a method on itself with advice applied. Otherwise, if an
	 * advised object invokes a method on this, no advice will be applied.
	 * @see AopContext
	 */
	boolean isExposeProxy();

	/**
设置是否预过滤此代理配置,使其仅包含适用的advisors(匹配此代理的目标类)

默认为“假”。如果advisors已经被预先过滤,则将此设置为“true”,这意味着在为代理调用构建实际advisors链时可以跳过 ClassFilter 检查。
	 */
	void setPreFiltered(boolean preFiltered);

	/**
	 * Return whether this proxy configuration is pre-filtered so that it only
	 * contains applicable advisors (matching this proxy's target class).
	 */
	boolean isPreFiltered();


//操作当前代理对象advisors的相关方法
	Advisor[] getAdvisors();
	default int getAdvisorCount() 
		return getAdvisors().length;
	
	void addAdvisor(Advisor advisor) throws AopConfigException;
	void addAdvisor(int pos, Advisor advisor) throws AopConfigException;
	boolean removeAdvisor(Advisor advisor);
	void removeAdvisor(int index) throws AopConfigException;
	int indexOf(Advisor advisor);
	boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException;

//操作当前代理对象advice的相关方法
	void addAdvice(Advice advice) throws AopConfigException;
	void addAdvice(int pos, Advice advice) throws AopConfigException;
	boolean removeAdvice(Advice advice);
	int indexOf(Advice advice);



	String toProxyConfigString();


AdvisedSupport—Advised接口的实现类

它最重要的一个方法是:提供getInterceptorsAndDynamicInterceptionAdvice方法用来获取对应代理方法对应有效的拦截器链

AdvisedSupport本身不会提供创建代理的任何方法,专注于生成拦截器链。委托给ProxyCreatorSupport去创建代理对象

public class AdvisedSupport extends ProxyConfig implements Advised 
	private static final long serialVersionUID = 2651364800145442165L;

	/**
	 * Canonical TargetSource when there's no target, and behavior is
	 * supplied by the advisors.
	 */
	public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;


	/** Package-protected to allow direct access for efficiency. */
	TargetSource targetSource = EMPTY_TARGET_SOURCE;

	/** Whether the Advisors are already filtered for the specific target class. */
	private boolean preFiltered = false;

	/**生产当前方法关联的拦截器链集合*/
	AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();

	/** Cache with Method as key and advisor chain List as value. */
	private transient Map<MethodCacheKey, List<Object>> methodCache;

	/**
	 * Interfaces to be implemented by the proxy. Held in List to keep the order
	 * of registration, to create JDK proxy with specified order of interfaces.
	 * 代理类需要继承的接口
	 */
	private List<Class<?>> interfaces = new ArrayList<>();

	/**
	 * List of Advisors. If an Advice is added, it will be wrapped
	 * in an Advisor before being added to this List.
	 */
	private List<Advisor> advisors = new ArrayList<>();



	/**
	 该方法是该类中最重要的一个方法,因此我把他移动到了最前面
	 * Determine a list of MethodInterceptor objects
	 * for the given method, based on this configuration.
	 * 获取当前方法对应的拦截器链
	 */
	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) 
	//先构造缓存key
		MethodCacheKey cacheKey = new MethodCacheKey(method);
	//先看缓存中是否存在
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) 
			//缓存中没有,再通过advisorChainFactory得到当前方法关联的拦截器链,放入缓存中
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		
		return cached;
	


	/**
	 * No-arg constructor for use as a JavaBean.
	 */
	public AdvisedSupport() 
		this.methodCache = new ConcurrentHashMap<>(32);
	

	/**
	 * Create a AdvisedSupport instance with the given parameters.
	 */
	public AdvisedSupport(Class<?>... interfaces) 
		this();
		setInterfaces(interfaces);
	


	/**
	 * Set the given object as target.
	 * Will create a SingletonTargetSource for the object.
	 */
	public void setTarget(Object target) 
	   //所有的目标对象都会被包装为TargetSource---默认为SingletonTargetSource
		setTargetSource(new SingletonTargetSource(target));
	

	@Override
	public void setTargetSource(@Nullable TargetSource targetSource) 
		this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
	

	@Override
	public TargetSource getTargetSource() 
		return this.targetSource;
	

	public void setTargetClass(@Nullable Class<?> targetClass) 
		this.targetSource = EmptyTargetSource.forClass(targetClass);
	

	@Override
	@Nullable
	public Class<?> getTargetClass() 
		return this.targetSource.getTargetClass();
	

	@Override
	public void setPreFiltered(boolean preFiltered) 
		this.preFiltered = preFiltered;
	

	@Override
	public boolean isPreFiltered() 
		return this.preFiltered;
	

	/**
	 * Set the advisor chain factory to use.
	 */
	public void setAdvisorChainFactory(AdvisorChainFactory advisorChainFactory) 
		Assert.notNull(advisorChainFactory, "AdvisorChainFactory must not be null");
		this.advisorChainFactory = advisorChainFactory;
	

	/**
	 * Return the advisor chain factory to use (never @code null).
	 */
	public AdvisorChainFactory getAdvisorChainFactory() 
		return this.advisorChainFactory;
	


	/**
	 * Set the interfaces to be proxied.
	 */
	public void setInterfaces(Class<?>... interfaces) 
		Assert.notNull(interfaces, "Interfaces must not be null");
		this.interfaces.clear();
		for (Class<?> ifc : interfaces) 
			addInterface(ifc);
		
	

	/**
	 * Add a new proxied interface.
	 */
	public void addInterface(Class<?> intf) 
		Assert.notNull(intf, "Interface must not be null");
		if (!intf.isInterface()) 
			throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
		
		if (!this.interfaces.contains(intf)) 
			this.interfaces.add(intf);
			adviceChanged();
		
	

	public boolean removeInterface(Class<?> intf) 
		return this.interfaces.remove(intf);
	

	@Override
	public Class<?>[] getProxiedInterfaces() 
		return ClassUtils.toClassArray(this.interfaces);
	

//当前接口是否被代理了
	@Override
	public boolean isInterfaceProxied(Class<?> intf) 
		for (Class<?> proxyIntf : this.interfaces) 
			if (intf.isAssignableFrom(proxyIntf)) 
				return true;
			
		
		return false;
	


	@Override
	public final Advisor[] getAdvisors(以上是关于Spring读源码系列之AOP--03---aop底层基础类学习的主要内容,如果未能解决你的问题,请参考以下文章

Spring读源码系列之AOP--04---proxyFactory创建代理对象

Spring读源码系列之AOP--02---aop基本概念扫盲---下

Spring读源码系列之AOP--08--aop执行完整源码流程之自动代理创建器导入的两种方式

Spring读源码系列之AOP--05---aop常用工具类学习

Spring读源码系列之AOP--07---aop自动代理创建器(拿下AOP的最后一击)

Spring读源码系列之AOP--06---AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义