溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

spring-AOP原理與應(yīng)用

發(fā)布時間:2020-06-23 00:23:01 來源:網(wǎng)絡(luò) 閱讀:5640 作者:叫我北北 欄目:開發(fā)技術(shù)
spring-AOP原理與應(yīng)用

spring-AOP原理與應(yīng)用


什么是AOP

spring-AOP原理與應(yīng)用

Spring是解決實際開發(fā)中的一些問題:

* AOP解決OOP中遇到的一些問題.OOP的延續(xù)和擴(kuò)展.

AOP作用

    對程序進(jìn)行增強(qiáng):不修改源碼的情況下.

    * AOP可以進(jìn)行權(quán)限校驗,日志記錄,性能監(jiān)控,事務(wù)控制.

SpringAOP的由來:

    AOP最早由AOP聯(lián)盟的組織提出的,制定了一套規(guī)范.SpringAOP思想引入到框架中,必須遵守AOP聯(lián)盟的規(guī)范.

底層實現(xiàn):

    代理機(jī)制:

    * Spring的AOP的底層用到兩種代理機(jī)制:

        * JDK的動態(tài)代理 :針對實現(xiàn)了接口的類產(chǎn)生代理.

        * Cglib的動態(tài)代理 :針對沒有實現(xiàn)接口的類產(chǎn)生代理. 應(yīng)用的是底層的字節(jié)碼增強(qiáng)的技術(shù) 生成當(dāng)前類的子類對象.

 

動態(tài)代理

1 運(yùn)行時實現(xiàn)指定的接口

想實現(xiàn)某個接口,你需要寫一個類,然后在類名字的后面給出“implementsXXX接口。這才是實現(xiàn)某個接口:

public interface MyInterface {
    void fun1();
    void fun2();
}
public class MyInterfaceImpl implements MyInterface {
    public void fun1() {
        System.out.println("fun1()");
    }
     
    public void fun2() {
        System.out.println("fun2()");
    }
}

上面的代碼對我們來說沒有什么新鮮感,我們要說的是動態(tài)代理技術(shù)可以通過一個方法調(diào)用就可以生成一個對指定接口的實現(xiàn)類對象。

Class[] cs = {MyInterface.class};

MyInterface mi = (MyInterface)Proxy.newProxyInstance(loader, cs, h);

 

上面代碼中,Proxy類的靜態(tài)方法newProxyInstance()方法生成了一個對象,這個對象實現(xiàn)了cs數(shù)組中指定的接口。沒錯,返回值miMyInterface接口的實現(xiàn)類。你不要問這個類是哪個類,你只需要知道miMyInterface接口的實現(xiàn)類就可以了。你現(xiàn)在也不用去管loaderh這兩個參數(shù)是什么東東,你只需要知道,Proxy類的靜態(tài)方法newProxyInstance()方法返回的方法是實現(xiàn)了指定接口的實現(xiàn)類對象,甚至你都沒有看見實現(xiàn)類的代碼。

動態(tài)代理就是在運(yùn)行時生成一個類,這個類會實現(xiàn)你指定的一組接口,而這個類沒有.java文件,是在運(yùn)行時生成的,你也不用去關(guān)心它是什么類型的,你只需要知道它實現(xiàn)了哪些接口即可。

2 newProxyInstance()方法的參數(shù)

Proxy類的newInstance()方法有三個參數(shù):

ClassLoader loader:它是類加載器類型,你不用去理睬它,你只需要知道怎么可以獲得它就可以了:MyInterface.class.getClassLoader()就可以獲取到ClassLoader對象,沒錯,只要你有一個Class對象就可以獲取到ClassLoader對象;

Class[] interfaces:指定newProxyInstance()方法返回的對象要實現(xiàn)哪些接口,沒錯,可以指定多個接口,例如上面例子只我們只指定了一個接口:Class[] cs = {MyInterface.class};

InvocationHandler h:它是最重要的一個參數(shù)!它是一個接口!它的名字叫調(diào)用處理器!你想一想,上面例子中mi對象是MyInterface接口的實現(xiàn)類對象,那么它一定是可以調(diào)用fun1()fun2()方法了,難道你不想調(diào)用一下fun1()fun2()方法么,它會執(zhí)行些什么東東呢?其實無論你調(diào)用代理對象的什么方法,它都是在調(diào)用InvocationHandlerinvoke()方法!

public static void main(String[] args) {
    Class[] cs = {MyInterface.class};
    ClassLoader loader = MyInterface.class.getClassLoader();
    InvocationHandler h = new InvocationHandler() {
        public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
            System.out.println("無論你調(diào)用代理對象的什么方法,其實都是在調(diào)用invoke()...");
            return null;
        }
    };
    MyInterface mi = (MyInterface)Proxy.newProxyInstance(loader, cs, h);
    mi.fun1();
    mi.fun2();
}

  InvocationHandler接口只有一個方法,即invoke()方法!它是對代理對象所有方法的唯一實現(xiàn)。也就是說,無論你調(diào)用代理對象上的哪個方法,其實都是在調(diào)用InvocationHandlerinvoke()方法。

想象中的類:

class X implements MyInterface {
    private InvocationHandler h;
    public X(InvocationHandler h) {
        this.h = h;
    }
    
    public void fun1() {
        h.invoke();
    }
    public void fun2() {
        h.invoke();
    }
}

注意,X類是我們用來理解代理對象與InvocationHandler之間的關(guān)系的,但它是不存在的類。是我們想象出來的!也就是說,它是用來說明,無論你調(diào)用代理對象的哪個方法,最終調(diào)用的都是調(diào)用處理器的invoke()方法。

3 InvocationHandlerinvoke()方法

spring-AOP原理與應(yīng)用


InvocationHandler的invoke()方法的參數(shù)有三個:

Object proxy:代理對象,也就是Proxy.newProxyInstance()方法返回的對象,通常我們用不上它;

Method method:表示當(dāng)前被調(diào)用方法的反射對象,例如mi.fun1(),那么method就是fun1()方法的反射對象;

Object[] args:表示當(dāng)前被調(diào)用方法的參數(shù),當(dāng)然mi.fun1()這個調(diào)用是沒有參數(shù)的,所以args是一個零長數(shù)組。

  最后要說的是invoke()方法的返回值為Object類型,它表示當(dāng)前被調(diào)用的方法的返回值,當(dāng)然mi.fun1()方法是沒有返回值的,所以invoke()返回的就必須是null了。

public static void main(String[] args) {
    Class[] cs = {MyInterface.class};
    ClassLoader loader = MyInterface.class.getClassLoader();
    InvocationHandler h = new InvocationHandler() {
    public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
        System.out.println("當(dāng)前調(diào)用的方法是:" + method.getName());
        return null;
    }
    };
    MyInterface mi = (MyInterface)Proxy.newProxyInstance(loader, cs, h);
    mi.fun1();
    mi.fun2();
}

AOP的開發(fā)中的相關(guān)術(shù)語:

Joinpoint(連接點):所謂連接點是指那些被攔截到的點。在spring,這些點指的是方法,因為spring只支持方法類型的連接點.

Pointcut(切入點):所謂切入點是指我們要對哪些Joinpoint進(jìn)行攔截的定義.

Advice(通知/增強(qiáng)):所謂通知是指攔截到Joinpoint之后所要做的事情就是通知.通知分為前置通知,后置通知,異常通知,最終通知,環(huán)繞通知(切面要完成的功能)

Introduction(引介):引介是一種特殊的通知在不修改類代碼的前提下, Introduction可以在運(yùn)行期為類動態(tài)地添加一些方法或Field.

Target(目標(biāo)對象):代理的目標(biāo)對象

Weaving(織入):是指把增強(qiáng)應(yīng)用到目標(biāo)對象來創(chuàng)建新的代理對象的過程.

spring采用動態(tài)代理織入,而AspectJ采用編譯期織入和類裝在期織入

Proxy(代理):一個類被AOP織入增強(qiáng)后,就產(chǎn)生一個結(jié)果代理類

Aspect(切面): 是切入點和通知(引介)的結(jié)合

Spring使用AspectJ進(jìn)行AOP的開發(fā):XML的方式

引入相應(yīng)的jar

* spring的傳統(tǒng)AOP的開發(fā)的包

    spring-aop-4.2.4.RELEASE.jar

    com.springsource.org.aopalliance-1.0.0.jar

* aspectJ的開發(fā)包:

    com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

    spring-aspects-4.2.4.RELEASE.jar

spring-AOP原理與應(yīng)用


引入Spring的配置文件

引入AOP約束:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>


通知類型

    前置通知 :在目標(biāo)方法執(zhí)行之前執(zhí)行

    后置通知 :在目標(biāo)方法執(zhí)行之后執(zhí)行

    環(huán)繞通知 :在目標(biāo)方法執(zhí)行前和執(zhí)行后執(zhí)行

    異常拋出通知:在目標(biāo)方法執(zhí)行出現(xiàn) 異常的時候執(zhí)行

    最終通知 :無論目標(biāo)方法是否出現(xiàn)異常最終通知都會執(zhí)行

切入點表達(dá)式

    execution(表達(dá)式)

    表達(dá)式:

    [方法訪問修飾符] 方法返回值 包名.類名.方法名(方法的參數(shù))

    public * cn.spring.dao.*.*(..)

    * cn.spring.dao.*.*(..)

    * cn.spring.dao.UserDao+.*(..)

    * cn.spring.dao..*.*(..)

案例

spring-AOP原理與應(yīng)用


其他的增強(qiáng)的配置:
<!-- 配置切面類 -->
<bean id="myAspectXml" class="cn.itcast.spring.demo3.MyAspectXml"></bean>

<!-- 進(jìn)行aop的配置 -->
<aop:config>
    <!-- 配置切入點表達(dá)式:哪些類的哪些方法需要進(jìn)行增強(qiáng) -->
    <aop:pointcut expression="execution(* cn.spring.demo3.*Dao.save(..))" id="pointcut1"/>
    <aop:pointcut expression="execution(* cn.spring.demo3.*Dao.delete(..))" id="pointcut2"/>
    <aop:pointcut expression="execution(* cn.spring.demo3.*Dao.update(..))" id="pointcut3"/>
    <aop:pointcut expression="execution(* cn.spring.demo3.*Dao.find(..))" id="pointcut4"/>
    <!-- 配置切面 -->
    <aop:aspect ref="myAspectXml">
        <aop:before method="before" pointcut-ref="pointcut1"/>
        <aop:after-returning method="afterReturing" pointcut-ref="pointcut2"/>
        <aop:around method="around" pointcut-ref="pointcut3"/>
        <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4"/>
        <aop:after method="after" pointcut-ref="pointcut4"/>
    </aop:aspect>
</aop:config>


Spring使用AspectJ進(jìn)行AOP的開發(fā):注解的方式

引入相關(guān)的jar:
引入Spring的配置文件

引入AOP約束:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>
編寫目標(biāo)類:
public class ProductDao {
public void save(){
System.out.println("保存商品...");
}
public void update(){
System.out.println("修改商品...");
}
public void delete(){
System.out.println("刪除商品...");
}
public void find(){
System.out.println("查詢商品...");
}
}
配置目標(biāo)類:
<!-- 目標(biāo)類============ -->
     <bean id="productDao" class="cn.spring.demo4.ProductDao"></bean>

開啟aop注解的自動代理:
<aop:aspectj-autoproxy/>
AspectJAOP的注解:

@Aspect:定義切面類的注解

 

通知類型:

    * @Before   :前置通知

    * @AfterReturing  :后置通知

    * @Around   :環(huán)繞通知

    * @After    :最終通知

    * @AfterThrowing  :異常拋出通知.

 

@Pointcut:定義切入點的注解

編寫切面類:
@Aspect
public class MyAspectAnno {
 
    @Before("MyAspectAnno.pointcut1()")
    public void before(){
    System.out.println("前置通知===========");
    }
    
    @Pointcut("execution(* cn.spring.demo4.ProductDao.save(..))")
    private void pointcut1(){}
}


配置切面:
<!-- 配置切面類 -->
     <bean id="myAspectAnno" class="cn.spring.demo4.MyAspectAnno"></bean>

其他通知的注解:
@Aspect
public class MyAspectAnno {
 
    @Before("MyAspectAnno.pointcut1()")
    public void before(){
        System.out.println("前置通知===========");
    }
    
    @AfterReturning("MyAspectAnno.pointcut2()")
    public void afterReturning(){
        System.out.println("后置通知===========");
    }
    
    @Around("MyAspectAnno.pointcut3()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("環(huán)繞前通知==========");
        Object obj = joinPoint.proceed();
        System.out.println("環(huán)繞后通知==========");
        return obj;
    }
    
    @AfterThrowing("MyAspectAnno.pointcut4()")
    public void afterThrowing(){
        System.out.println("異常拋出通知========");
    }
    
    @After("MyAspectAnno.pointcut4()")
    public void after(){
        System.out.println("最終通知==========");
    }
    
    @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.save(..))")
    private void pointcut1(){}
    @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.update(..))")
    private void pointcut2(){}
    @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.delete(..))")
    private void pointcut3(){}
    @Pointcut("execution(* cn.itcast.spring.demo4.ProductDao.find(..))")
    private void pointcut4(){}
}

源碼解析

對于上面注解方式的aop操作,我覺得有必要了解一下源碼實現(xiàn),但是總感覺能力很經(jīng)驗還不足以讀懂源碼,這里先開個頭,之后覺得時機(jī)到了再讀:

spring-AOP原理與應(yīng)用

spring中的自定義注解,如果聲明了自定義注解,那么就一定會在程序中的某個地方注冊了對于的解析器,所以找見了上圖的類所在的位置。

public class AopNamespaceHandler extends NamespaceHandlerSupport {

   /**
    * Register the {@link BeanDefinitionParser BeanDefinitionParsers} for the
    * '{@code config}', '{@code spring-configured}', '{@code aspectj-autoproxy}'
    * and '{@code scoped-proxy}' tags.
    */
   @Override
   public void init() {
      // In 2.0 XSD as well as in 2.1 XSD.
      registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
      //這里對標(biāo)簽aspectj-autoproxy注冊,算是源碼的入口
      registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
      registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

      // Only in 2.0 XSD: moved to context namespace as of 2.1
      registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
   }

}

一旦遇到注解就會使用解析器AspectJAutoProxyBeanDefinitionParser進(jìn)行解析,它解析的代碼邏輯是:

class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {

   @Override
   @Nullable
   public BeanDefinition parse(Element element, ParserContext parserContext) {
      AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
      extendBeanDefinition(element, parserContext);
      return null;
   }

   private void extendBeanDefinition(Element element, ParserContext parserContext) {
      BeanDefinition beanDef =
            parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
      if (element.hasChildNodes()) {
         addIncludePatterns(element, parserContext, beanDef);
      }
   }

   private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {
      ManagedList<TypedStringValue> includePatterns = new ManagedList<>();
      NodeList childNodes = element.getChildNodes();
      for (int i = 0; i < childNodes.getLength(); i++) {
         Node node = childNodes.item(i);
         if (node instanceof Element) {
            Element includeElement = (Element) node;
            TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));
            valueHolder.setSource(parserContext.extractSource(includeElement));
            includePatterns.add(valueHolder);
         }
      }
      if (!includePatterns.isEmpty()) {
         includePatterns.setSource(parserContext.extractSource(element));
         beanDef.getPropertyValues().add("includePatterns", includePatterns);
      }
   }

}

AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser,對于BeanDefinitionParser接口的統(tǒng)一實現(xiàn)都是從parse函數(shù)開始的。

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
      ParserContext parserContext, Element sourceElement) {
//1.注冊或者升級BeanDefinition 
   BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
         parserContext.getRegistry(), parserContext.extractSource(sourceElement));
//2.處理proxy-target-class以及expose-proxy屬性
   useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
   //注冊組件并通知監(jiān)聽
   registerComponentIfNecessary(beanDefinition, parserContext);
}


到這就是對自定義注解的處理代碼,具體邏輯由于類太多還整理不了。


結(jié)合網(wǎng)上看的資料,對于創(chuàng)建aop代碼可以分為以下步驟:

    1.獲取增強(qiáng)器或者獲取增強(qiáng)方法

    2.根據(jù)獲取的增強(qiáng)進(jìn)行代理,(創(chuàng)建代碼的方式是通過代理工廠實現(xiàn)的:)

核心類是:

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

	@Nullable
	protected static final Object[] DO_NOT_PROXY = null;

	protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];

	protected final Log logger = LogFactory.getLog(getClass());

	private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();

	private boolean freezeProxy = false;

	private String[] interceptorNames = new String[0];

	private boolean applyCommonInterceptorsFirst = true;

	@Nullable
	private TargetSourceCreator[] customTargetSourceCreators;

	@Nullable
	private BeanFactory beanFactory;

	private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	private final Set<Object> earlyProxyReferences = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);

	private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);


	@Override
	public void setFrozen(boolean frozen) {
		this.freezeProxy = frozen;
	}

	@Override
	public boolean isFrozen() {
		return this.freezeProxy;
	}

	public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
		this.advisorAdapterRegistry = advisorAdapterRegistry;
	}

	public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
		this.customTargetSourceCreators = targetSourceCreators;
	}

	public void setInterceptorNames(String... interceptorNames) {
		this.interceptorNames = interceptorNames;
	}

	public void setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst) {
		this.applyCommonInterceptorsFirst = applyCommonInterceptorsFirst;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
	}

	@Nullable
	protected BeanFactory getBeanFactory() {
		return this.beanFactory;
	}

	@Override
	@Nullable
	public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
		if (this.proxyTypes.isEmpty()) {
			return null;
		}
		Object cacheKey = getCacheKey(beanClass, beanName);
		return this.proxyTypes.get(cacheKey);
	}

	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
		return null;
	}

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

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		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;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
	}

	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		return true;
	}

	@Override
	public PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {

		return pvs;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}

	//*********可以從這里看整個類的代碼
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
			//如果適合被代理,則需要封裝指定的bean
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

	protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
		if (StringUtils.hasLength(beanName)) {
			return (FactoryBean.class.isAssignableFrom(beanClass) ?
					BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
		}
		else {
			return beanClass;
		}
	}

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

		// Create proxy if we have advice.如果存在增強(qiáng)方法則創(chuàng)建增強(qiáng)
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			//創(chuàng)建代理
			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;
	}

	protected boolean isInfrastructureClass(Class<?> beanClass) {
		boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
				Pointcut.class.isAssignableFrom(beanClass) ||
				Advisor.class.isAssignableFrom(beanClass) ||
				AopInfrastructureBean.class.isAssignableFrom(beanClass);
		if (retVal && logger.isTraceEnabled()) {
			logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
		}
		return retVal;
	}

	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		return false;
	}

	@Nullable
	protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
		// We can't create fancy target sources for directly registered singletons.
		if (this.customTargetSourceCreators != null &&
				this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
			for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
				TargetSource ts = tsc.getTargetSource(beanClass, beanName);
				if (ts != null) {
					// Found a matching TargetSource.
					if (logger.isDebugEnabled()) {
						logger.debug("TargetSourceCreator [" + tsc +
								" found custom TargetSource for bean with name '" + beanName + "'");
					}
					return ts;
				}
			}
		}

		// No custom TargetSource found.
		return null;
	}

	/*創(chuàng)建代理,spring都委托給proxyfactory去處理,在下面進(jìn)行了一些初始化操作,主要包括以下內(nèi)容:
	1.獲取當(dāng)前類中的屬性
	2.添加代理接口
	3.封裝advisor并加入到ProxyFactory中
	4.設(shè)置需要代理的類
	5.對ProxyFactory進(jìn)一步封裝
	6.進(jìn)行獲取代理操作*/
	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();
		//獲取相關(guān)的屬性
		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());
	}

	protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
		return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
				AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
	}

	protected boolean advisorsPreFiltered() {
		return false;
	}

	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// Handle prototypes correctly...
		Advisor[] commonInterceptors = resolveInterceptorNames();

		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
			if (commonInterceptors.length > 0) {
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		if (logger.isDebugEnabled()) {
			int nrOfCommonInterceptors = commonInterceptors.length;
			int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
			logger.debug("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
					" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
		}

		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

	private Advisor[] resolveInterceptorNames() {
		BeanFactory bf = this.beanFactory;
		ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
		List<Advisor> advisors = new ArrayList<>();
		for (String beanName : this.interceptorNames) {
			if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
				Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
				Object next = bf.getBean(beanName);
				advisors.add(this.advisorAdapterRegistry.wrap(next));
			}
		}
		return advisors.toArray(new Advisor[advisors.size()]);
	}

	protected void customizeProxyFactory(ProxyFactory proxyFactory) {
	}


	@Nullable
	protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
			@Nullable TargetSource customTargetSource) throws BeansException;

}




向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI