概述
Spring經常被人提及的就是IOC和AOP敬察,前邊在介紹IOC的時候艇挨,我們已經提及到了AOP,還記得起來嗎?
在《Spring源碼閱讀----Spring IoC之finishBeanFactoryInitialization(續(xù))很重要的createBean》一文中恤溶,介紹到有些實現了InstantiationAwareBeanPostProcessor接口的AbstractAutoProxyCreator類,其子類AnnotationAwareAutoProxyCreator是個很重要的類帜羊。
啥是AOP
AOP(Aspect Oriented Programming)宏娄,面向切面思想,可以百度一下其概念逮壁。比如日志打印等邊緣需求會散落在多處業(yè)務中孵坚,重復寫冗余代碼會影響項目維護,而AOP就是將這類主業(yè)務以外的代碼提取出來窥淆,使其分離卖宠,然后在這些業(yè)務中尋找切入點,然后將分離的非業(yè)務代碼切入業(yè)務中忧饭。
實踐一下
下面來看一個例子,在原來的SSM demo里改造
- 在pom文件中加入依賴包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
- 創(chuàng)建一個切面類AopTest
@Component
@Aspect
public class AopTest {
@Pointcut("execution(* com.zhlab..ssm.demo.web.controller.TestController.*(..))")
public void pointCut(){}
@Before("pointCut()")
public void beforeMethod(JoinPoint joinPoint){
System.out.println("前置通知before start");
String methodName = joinPoint.getSignature().getName();
System.out.println("前置通知before end");
}
@After("pointCut()")
public void afterMethod(JoinPoint joinPoint){
System.out.println("后置通知after start");
String methodName = joinPoint.getSignature().getName();
System.out.println("后置通知after end");
}
@Around("pointCut()")
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("環(huán)繞通知after start");
String methodName = joinPoint.getSignature().getName();
Object result = joinPoint.proceed();//執(zhí)行業(yè)務具體業(yè)務邏輯
System.out.println("環(huán)繞通知after end");
return result;
}
}
類上加上兩個注解@Component扛伍、@Aspect
注解@Aspect表示當前類是一個切面,添加@Component注解表示當前類需要初始化一個bean到Spring容器中,這個類里只使用了@Before词裤、@After刺洒、@Around三個方法注解,總的有以下幾個注解:
- @Before注解修飾方法表示當前方法會在連接點方法之前執(zhí)行
- @After注解修飾方法表示當前方法會在連接點之后執(zhí)行
- @Around注解修飾方法表示當前方法會在連接點之前和之后均會執(zhí)行
- @AfterThrowing注解修飾方法表示當前方法會在連接點拋異常之后執(zhí)行,如果不拋異常則不會執(zhí)行
- @AfterReturning注解修飾方法表示當前方法會在連接點返回結果時執(zhí)行吼砂,如果連接點方法是void逆航,則該注解不會生效
@Pointcut后可以寫execution和@Annotation
execution表達式里的各個號的含義:
"execution( com.zhlab..ssm.demo.web.controller.TestController.*(..))"
- 返回類型: 第一個 * 號的位置:表示返回值類型,* 表示方法返回類型無限制
- 包名以及類:表示需要攔截的包名渔肩,TestController指定了具體的類,如果這里改成 ..* 則表示controller包以及其子包下的所有類
- 方法: 第二個 * 號 表示 所有方法因俐,后面括號里面表示方法的參數,兩個句點表示任何參數
annotation() 表達式:
"@annotation(org.springframework.web.bind.annotation.GetMapping)"
然后使用該切面的話周偎,就會切入注解是 @GetMapping的所有方法抹剩。這種方式很適合處理 @GetMapping、@PostMapping蓉坎、@DeleteMapping等不同注解有各種特定處理邏輯的場景澳眷。
- 在配置文件中加入aop配置信息如下
<!-- 主要這個信息需要加在spring mvc配置文件里 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
- 啟動項目,然后訪問/test,效果如下:
如果method有多個切面的話蛉艾,我們可以使用@Order(1) 來排序钳踊,數字越小排前面衷敌。
好了其他的例子就不一一例舉了。
很重要的AnnotationAwareAutoProxyCreator
小結
<aop:aspectj-autoproxy />標簽的作用是聲明自動為Spring容器中那些配置@Aspectj注解的切面的bean創(chuàng)建代理箍土,織入切面
這個標簽需要加到spring-mvc的配置代碼中才起作用
(頭部標簽聲明需要加入xmlns:aop="http://www.springframework.org/schema/aop"逢享,xsi:schemaLocation中需要加入:http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd)
原理
<aop:aspectj-autoproxy>標簽的解析
在前文《Spring源碼閱讀----Spring IoC之BeanFactory罐监、ApplicationContext》中我們介紹過parseBeanDefinitions方法中吴藻,會解析自定義標簽
//xml解析過程中,調用了自定義標簽解析
delegate.parseCustomElement(ele);
//在BeanDefinitionParserDelegate類中執(zhí)行
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
// 注釋1 找到命名空間
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
// 注釋2 根據命名空間找到對應的 NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
// 注釋3 調用自定義的 NamespaceHandler 進行解析
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
}
會根據配置中的標簽命名空間 獲取 對應的NamespaceHandler弓柱,這里關注一下<aop:aspectj-autoproxy>標簽沟堡,它的handler是org.springframework.aop.config包下的AopNamespaceHandler:
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());
// 注釋 自定義注解,注冊解析器矢空,元素名是 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類中關注parse方法:
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// aop 注解的解析入口航罗,注冊 AnnotationAwareAspectJAutoProxyCreator
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
// 對注解中子類的處理
extendBeanDefinition(element, parserContext);
return null;
}
繼續(xù)看看AopNamespaceUtils類中的registerAspectJAnnotationAutoProxyCreatorIfNecessary如何執(zhí)行的:
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
// 通過工具類,注冊或升級 AspectJAnnotationAutoProxyCreator
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 處理 proxy-target-class 以及 expose-proxy 屬性
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 注冊AnnotationAwareAutoProxyCreator組件并通知屁药,讓監(jiān)聽器進行處理
registerComponentIfNecessary(beanDefinition, parserContext);
}
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
// 解析下面兩個屬性粥血,如果是 true,將它們加入代理注冊器的屬性列表中
// definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE)
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
// 處理 proxy-target-class 屬性
// 與代碼生成方式有關酿箭,在之后步驟中決定使用 jdk 動態(tài)代理 或 cglib
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
// 處理 expose-proxy 屬性
// 擴展增強复亏,有時候目標對象內部的自我調用無法實施切面中的增強,通過這個屬性可以同時對兩個方法進行增強
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
if (beanDefinition != null) {
// 注冊 的beanName 是 org.springframework.aop.config.internalAutoProxyCreator
parserContext.registerComponent(
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
}
}
所以以上缭嫡,就是注冊AnnotationAwareAutoProxyCreator的過程缔御。aop中創(chuàng)建代理對象是通過AnnotationAwareAutoProxyCreator來實現的。
AnnotationAwareAutoProxyCreator
先來看看AnnotationAwareAutoProxyCreator的類圖妇蛀,如下:
可以看到它的父類AbstractAutoProxyCreator實現了BeanPostProcessor接口的子接口InstantiationAwareBeanPostProcessor耕突,這里關注AbstractAutoProxyCreator執(zhí)行的postProcessBeforeInstantiation方法和postProcessAfterInitialization方法。
postProcessBeforeInstantiation方法
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// 切面 bean 實例化之前執(zhí)行的方法
// 根據beanClass和beanName獲取緩存的key
Object cacheKey = getCacheKey(beanClass, beanName);
// beanName 不存在 || 目標堆中不存在這個 bean
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,請在此處創(chuàng)建代理纵诞。
// 禁止目標bean的不必要的默認實例化:
// TargetSource將以自定義方式處理目標實例
//TargetSource實例相當于就是目標對象bean的封裝實例
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
// 獲取當前bean所有的增強數組
// 實際上委派給子類去實現 AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
// 根據增強數組為目標對象創(chuàng)建代理對象
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
//返回代理bean
return proxy;
}
return null;
}
postProcessAfterInitialization方法
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 組裝 key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 如果適合被代理蔼卡,則需要封裝指定的 bean
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
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;
}
// 給定的 bean 類是否代表一個基礎設施類雇逞,基礎設置類不應代理
//或者配置了指定 bean 不需要代理
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
// 如果存在增強方法則創(chuàng)建代理
//獲取當前bean所有的增強數組,也就是Advisor數組
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;
}
createProxy方法創(chuàng)建代理對象
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);
}
// 創(chuàng)建代理工廠對象,并復制當前類的屬性
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
// 決定對于給定 bean 是否應該使用 targetClass 而不是他的接口代理
if (!proxyFactory.isProxyTargetClass()) {
// 檢查 proxyTargetClass 設置以及 preserveTargetClass 屬性
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 添加代理接口
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 設置代理工廠屬性,將增強數組advisors和目標對象targetSource加入到代理工廠中
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
// 自定義定制代理
customizeProxyFactory(proxyFactory);
// 用來控制代理工廠被配置之后,是否含允許修改通知
// 缺省值為 false茁裙,不允許修改代理的配置
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 調用代理工廠類的getProxy方法創(chuàng)建代理對象
return proxyFactory.getProxy(getProxyClassLoader());
}
通過代碼執(zhí)行過程塘砸,我們可以發(fā)現是委托給ProxyFactory來創(chuàng)建代理對象的。
ProxyFactory的getProxy方法源碼:
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
//創(chuàng)建AopProxy對象
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
先是createAopProxy創(chuàng)建AopProxy對象 晤锥,然后通過getProxy獲取代理對象
那先來看DefaultAopProxyFactory類中的createAopProxy方法:
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 創(chuàng)建代理
//這里有兩種代理類型 1. JDK 動態(tài)代理 2. CGLIB 動態(tài)代理
// isOptimize 判斷是否采用優(yōu)化策略
//isProxyTargetClass: 該屬性對于<aop:aspectj-autoproxy/>標簽中的proxy-target-class屬性的值.表示是否代理目標類本身,而不是目標類的接口
//hasNoUserSuppliedProxyInterfaces :判斷是否存在代理接口
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.");
}
//如果目標對象是一個接口,則創(chuàng)建JDK動態(tài)代理對象
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//如果目標對象不是一個接口,則創(chuàng)建 CGLIB代理對象
return new ObjenesisCglibAopProxy(config);
}
else {
//創(chuàng)建JDK動態(tài)代理對象
return new JdkDynamicAopProxy(config);
}
}
如何選擇JDK動態(tài)代理(JdkDynamicAopProxy )還是CGLIB代理(ObjenesisCglibAopProxy)?
- 如果目標對象實現了接口掉蔬,默認情況下會采用JDK動態(tài)代理廊宪;但是可以通過配置 proxy-target-class屬性的值為true強制使用CGLIB代理,則代理的是目標對象的本身
- 如果目標對象沒有實現接口女轿,那么必須采用CGLIB創(chuàng)建代理對象
JdkDynamicAopProxy 源碼:
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
//....前面省略
//JdkDynamicAopProxy 構造函數,設置配置信息
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
} else {
this.advised = config;
}
}
//創(chuàng)建代理對象
public Object getProxy() {
return this.getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// Proxy.newProxyInstance 動態(tài)代理創(chuàng)建對象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
// 這個熟悉不箭启?因為實現了InvocationHandler接口,所以要重新invoke方法
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 處理 equals 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 獲取此方法的攔截鏈
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
// 檢查我們是否有任何切面邏輯蛉迹。如果我們不這樣做傅寡,我們可以回退直接反射調用目標,并避免創(chuàng)建 MethodInvocation北救。
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
//通過反射直接調用目標對象的方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
// 將攔截器封裝在 ReflectiveMethodInvocation荐操,便于使用 proceed 執(zhí)行攔截器
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
// 執(zhí)行攔截器鏈
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
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);
}
}
}
//....后面省略
}
ObjenesisCglibAopProxy繼承于CglibAopProxy類,其代理對象創(chuàng)建在CglibAopProxy類中實現:
@Override
public Object getProxy() {
// 不傳ClassLoader
return getProxy(null);
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
// 創(chuàng)建CGLIB Enhancer對象,并設置Enhancer對象的各種屬性
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
// 調用createProxyClassAndInstance方法創(chuàng)建代理對象
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +
": Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
enhancer.setInterceptDuringConstruction(false);
enhancer.setCallbacks(callbacks);
//執(zhí)行Enhancer的create方法創(chuàng)建代理對象
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
CGLIB 是一套強大的高性能的代碼生成工具包珍策,底層通過字節(jié)碼生成技術ASM框架來實現
什么是CGLIB,參考這篇文章《CGLIB動態(tài)代理的實現及原理》
從ObjenesisCglibAopProxy創(chuàng)建代理的對象的步驟可以看到:
最終是由Enhancer 對象來創(chuàng)建代理的,傳入的Callback數組托启,可以是實現了MethodInterceptor接口,并重寫intercept的攔截器對象攘宙。
每次代理對象執(zhí)行方法屯耸,會執(zhí)行Callback的intercept方法,會通過執(zhí)行invokeSuper方法來執(zhí)行目標類的方法蹭劈。
總結
好了疗绣,到這里我們就算完成了對Spring AOP的了解以及原理的分析。