盤(pán)點(diǎn) AOP : AOP 代理類(lèi)的創(chuàng)建
一 .前言
上一篇聊過(guò)了 AOP 的初始化 , 了解了 AOP 是如何通過(guò) PostProcess 完成 AOP 代理類(lèi)的創(chuàng)建 ,
二 . AOP 創(chuàng)建起點(diǎn)
AOP 創(chuàng)建的
// 在 AbstractAutoProxyCreator # wrapIfNecessary 中 , 發(fā)起了 createProxy 流程用于創(chuàng)建代理類(lèi)
createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean))
下面來(lái)看一下該邏輯中主要做了什么 :
復(fù)制代碼2.1 AbstractAutoProxyCreator 創(chuàng)建 Proxy 代理類(lèi)
C- AbstractAutoProxyCreator
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);
}
// 構(gòu)建一個(gè) ProxyFactory
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 構(gòu)建通知者
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// 獲取代理對(duì)象 -> 2.3 Aop 對(duì)象創(chuàng)建詳情
// org.springframework.aop.framework.ProxyFactory
return proxyFactory.getProxy(getProxyClassLoader());
}
復(fù)制代碼[PIC] : specificInterceptors 對(duì)象內(nèi)容

[Pro] AutoProxyUtils 的作用
C- AutoProxyUtils : 自動(dòng)代理的工具類(lèi)
M- shouldProxyTargetClass : 確定是否應(yīng)該用目標(biāo)類(lèi)而不是接口代理給定bean
M- determineTargetClass : 確定指定bean的原始目標(biāo)類(lèi),否則返回到常規(guī)的getType查找
M- exposeTargetClass : 公開(kāi)指定bean的給定目標(biāo)類(lèi)
M- isOriginalInstance : 根據(jù) ORIGINAL_INSTANCE_SUFFIX 確定給定bean名是否指示“原始實(shí)例”
static void exposeTargetClass(
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName, Class<?> targetClass) {
if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {
// ORIGINAL_TARGET_CLASS_ATTRIBUTE => org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass
beanFactory.getMergedBeanDefinition(beanName).setAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE, targetClass);
}
}
// PS : 這里設(shè)置了 Attribute 屬性 , 后面專(zhuān)門(mén)看一下該屬性會(huì)在什么情況下使用 >>>
復(fù)制代碼[Pro] ProxyFactory 的作用
用于編程使用的AOP代理的工廠(chǎng) , 該類(lèi)提供了在定制用戶(hù)代碼中獲取和配置AOP代理實(shí)例的簡(jiǎn)單方法
C- ProxyFactory
MC- ProxyFactory() : 創(chuàng)建一個(gè) ProxyFactory
MC- ProxyFactory(Object target) : 創(chuàng)建時(shí)通過(guò) target 設(shè)置 Target 和 Interfaces 屬性
MC- ProxyFactory(Class<?>... proxyInterfaces) : 沒(méi)有目標(biāo),只有接口且必須添加攔截器
MC- ProxyFactory(Class<?> proxyInterface, Interceptor interceptor) : 用于為單個(gè)攔截器創(chuàng)建代理的便利方法
MC- ProxyFactory(Class<?> proxyInterface, TargetSource targetSource) :為指定的TargetSource創(chuàng)建一個(gè)ProxyFactory,使代理實(shí)現(xiàn)指定的接口
M- getProxy() : 根據(jù)這個(gè)工廠(chǎng)的設(shè)置創(chuàng)建一個(gè)新的代理 , 可反復(fù)調(diào)用
M- getProxy(@Nullable ClassLoader classLoader) :
M- getProxy(Class<T> proxyInterface, Interceptor interceptor)
M- getProxy(Class<T> proxyInterface, TargetSource targetSource)
M- getProxy(TargetSource targetSource)
P- proxyInterface :
P- Interceptor :
P- TargetSource :
復(fù)制代碼[Pro] Advisor 作用
保存AOP通知(在連接點(diǎn)上要采取的動(dòng)作)的基本接口和決定通知(如切入點(diǎn))適用性的過(guò)濾器 , Advisor接口允許支持不同類(lèi)型的通知,比如 Before Advice 和 After Advice
C- Advisor : 通知器
M- getAdvice()
M- isPerInstance()
// 這里說(shuō)一說(shuō) Advisor 是什么時(shí)候調(diào)用的 >>>
復(fù)制代碼
2.2 buildAdvisors 創(chuàng)建通知對(duì)象
C- AbstractAutoProxyCreator
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// 2-2-1 : 將指定的攔截器名稱(chēng)解析為Advisor對(duì)象
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));
}
}
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 2-2-2 : 將指定的攔截器名稱(chēng)解析為Advisor對(duì)象
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
// 2-2-1 : 將指定的攔截器名稱(chēng)解析為Advisor對(duì)象
private Advisor[] resolveInterceptorNames() {
BeanFactory bf = this.beanFactory;
ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
List<Advisor> advisors = new ArrayList<>();
// 獲取通用 interceptor 對(duì)象 , 該對(duì)象可以 setInterceptorNames 設(shè)置
for (String beanName : this.interceptorNames) {
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
Object next = bf.getBean(beanName);
advisors.add(this.advisorAdapterRegistry.wrap(next));
}
}
return advisors.toArray(new Advisor[0]);
}
// 2-2-2 : 將指定的攔截器名稱(chēng)解析為Advisor對(duì)象
C- DefaultAdvisorAdapterRegistry
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
復(fù)制代碼三 . Aop 代理類(lèi)的創(chuàng)建流程
上一節(jié)通過(guò) CreateProxy 發(fā)起了代理的創(chuàng)建 , 此節(jié)來(lái)說(shuō)一下 ProxyFactory 的創(chuàng)建流程
Step 1 : 獲取代理類(lèi)主流程 => ProxyFactory
// 類(lèi)結(jié)構(gòu) ===================
C- ProxyFactory
E- ProxyCreatorSupport
public Object getProxy(@Nullable ClassLoader classLoader) {
// createAopProxy() => org.springframework.aop.framework.ObjenesisCglibAopProxy
return createAopProxy().getProxy(classLoader);
}
// ProxyCreatorSupport 是 ProxyFactory 的父類(lèi) , createAopProxy 會(huì)調(diào)用該類(lèi)方法
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
// 激活代理配置
activate();
}
// getAopProxyFactory() => org.springframework.aop.framework.DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
復(fù)制代碼Step 2 : AOP 代理工廠(chǎng)的選擇
// Aop 基于 Proxy 代理 , 主要接口為 AopProxy , 而 AopProxy 的創(chuàng)建接口類(lèi)為 AopProxyFactory ,
public interface AopProxyFactory {
/**
* 為給定的AOP配置創(chuàng)建一個(gè)AopProxy
*/
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}
// Aop 代理工廠(chǎng)默認(rèn)為 DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// config.isOptimize() : 返回代理是否應(yīng)該執(zhí)行主動(dòng)優(yōu)化
// config.isProxyTargetClass() : 返回是否直接代理目標(biāo)類(lèi)以及任何接口
// hasNoUserSuppliedProxyInterfaces(config) : 確定所提供的AdvisedSupport是否只指定了SpringProxy接口(或者根本沒(méi)有指定代理接口)
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);
}
}
// PS : Spring 類(lèi)默認(rèn)會(huì)使用 JdkDynamicAopProxy , 自行定制的 AOP 類(lèi)通常使用 CglibAopProxy
可以通過(guò)以下幾種方式配置 :
// 方式一 : 構(gòu)建 Bean 時(shí)可以通過(guò)配置切換 , 例如 :
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ExecutableValidator.class)
@ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider")
@Import(PrimaryDefaultValidatorPostProcessor.class)
public class ValidationAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public static MethodValidationPostProcessor methodValidationPostProcessor(Environment environment,
@Lazy Validator validator) {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
// 設(shè)置代理目標(biāo)對(duì)象
boolean proxyTargetClass = environment.getProperty("spring.aop.proxy-target-class", Boolean.class, true);
processor.setProxyTargetClass(proxyTargetClass);
processor.setValidator(validator);
return processor;
}
}
// 方式二 : 配置 AOP 代理方式
1. 通過(guò) EnableAspectJAutoProxy 配置
2. 通過(guò)屬性 spring.aop.proxy-target-class 進(jìn)行配置
復(fù)制代碼Step 3-1 : CglibAopProxy 創(chuàng)建代理類(lèi)
C- CglibAopProxy
public Object getProxy(@Nullable ClassLoader classLoader) {
try {
Class<?> rootClass = this.advised.getTargetClass();
Class<?> proxySuperClass = rootClass;
// String CGLIB_CLASS_SEPARATOR = "$$";
// 包含 $$
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// 檢查是否已經(jīng)驗(yàn)證了所提供的Class,如果沒(méi)有,則驗(yàn)證它
validateClassIfNecessary(proxySuperClass, classLoader);
// 配置 CGLIB 增強(qiáng) -> RPO31001
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 ClassLoaderAwareGeneratorStrategy(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);
// 生成代理類(lèi)并創(chuàng)建代理實(shí)例
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);
// 通過(guò)是否存在構(gòu)造參數(shù)分別創(chuàng)建
return (this.constructorArgs != null && this.constructorArgTypes != null ?
enhancer.create(this.constructorArgTypes, this.constructorArgs) :
enhancer.create());
}
// RPO31001 補(bǔ)充 : Enhancer 的作用
通常我們常見(jiàn)的代理方式是通過(guò) Proxy 類(lèi) , 而 Enhancer 也是一個(gè)方法代理類(lèi) , Proxy是基于接口的方式進(jìn)行代理,Enhancer是基于繼承的方式代理
復(fù)制代碼Step 3-2 : JdkDynamicAopProxy
// JdkDynamicAopProxy 構(gòu)建代理類(lèi)
public Object getProxy(@Nullable ClassLoader classLoader) {
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 創(chuàng)建代理類(lèi)
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
復(fù)制代碼AopProxy 代理體系

Spring 中的代理類(lèi)通常有 2個(gè)類(lèi) : CglibAopProxy / JdkDynamicAopProxy
// [Pro] : 如何切換 AopProxy 代理類(lèi)型
復(fù)制代碼四 . 要點(diǎn)深入
4.1 ORIGINAL_TARGET_CLASS_ATTRIBUTE 屬性的使用
// Step 1 : AbstractApplicationContext # refresh
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
try {
//.................
// 實(shí)例化所有剩余的(非lazy-init)單例
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
//........
}
}
// PS : 可以看到 , 在主流程倒數(shù)第二步中 ,
// EventListenerMethodProcessor : 對(duì)標(biāo)注了 @EventListener 的方法進(jìn)行解析, 然后轉(zhuǎn)換為一個(gè) ApplicationListener
// Step 2: C- EventListenerMethodProcessor # afterSingletonsInstantiated
public void afterSingletonsInstantiated() {
ConfigurableListableBeanFactory beanFactory = this.beanFactory;
String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
Class<?> type = null;
try {
// 確定指定bean的原始目標(biāo)類(lèi)
// Step 2-1 : 獲取 originalTargetClass
// beanName -> org.springframework.context.annotation.internalConfigurationAnnotationProcessor
// type -> org.springframework.context.annotation.ConfigurationClassPostProcessor
type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
}
catch (Throwable ex) {
//...............
}
if (type != null) {
if (ScopedObject.class.isAssignableFrom(type)) {
try {
Class<?> targetClass = AutoProxyUtils.determineTargetClass(
beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
if (targetClass != null) {
type = targetClass;
}
}
catch (Throwable ex) {
//...............
}
}
try {
// Step 2-3 : 獲取 originalTargetClass
processBean(beanName, type);
}
catch (Throwable ex) {
//...............
}
}
}
}
}
// Step 2-1 : 從 BeanDefinition 中獲取屬性 originalTargetClass
String ORIGINAL_TARGET_CLASS_ATTRIBUTE = Conventions.getQualifiedAttributeName(AutoProxyUtils.class, "originalTargetClass");
BeanDefinition bd = beanFactory.getMergedBeanDefinition(beanName);
Class<?> targetClass = (Class<?>) bd.getAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE);
// Step 2-2 : 查找原始目標(biāo)類(lèi) , 可以看到 , 通常查詢(xún)的類(lèi)都是 internalXXX 開(kāi)頭的類(lèi) , 該類(lèi)為 beanDefinitionNames 中創(chuàng)建
public static Class<?> determineTargetClass(
ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {
if (beanName == null) {
return null;
}
if (beanFactory.containsBeanDefinition(beanName)) {
BeanDefinition bd = beanFactory.getMergedBeanDefinition(beanName);
Class<?> targetClass = (Class<?>) bd.getAttribute(ORIGINAL_TARGET_CLASS_ATTRIBUTE);
if (targetClass != null) {
return targetClass;
}
}
return beanFactory.getType(beanName);
}
// Step 2-3 : 該方法省略 , 主要是 EventListener 注解的處理 , 和主流程無(wú)關(guān)
private void processBean(final String beanName, final Class<?> targetType)
復(fù)制代碼4.2 AOP Cglib 配置流程
通常基礎(chǔ)的AOP 代理是通過(guò)
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration$CglibAutoProxyConfiguration
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// h
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
//
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
// AUTO_PROXY_CREATOR_BEAN_NAME => org.springframework.aop.config.internalAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
復(fù)制代碼補(bǔ)充一 : EnableAspectJAutoProxy
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
復(fù)制代碼補(bǔ)充二 : AopAutoConfiguration 自動(dòng)配置類(lèi)
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
public class AopAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Advice.class)
static class AspectJAutoProxyingConfiguration {
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false",
matchIfMissing = false)
static class JdkDynamicAutoProxyConfiguration {
}
@Configuration(proxyBeanMethods = false)
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class CglibAutoProxyConfiguration {
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.aspectj.weaver.Advice")
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true)
static class ClassProxyingConfiguration {
ClassProxyingConfiguration(BeanFactory beanFactory) {
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
}
}
}
復(fù)制代碼補(bǔ)充三 : org.springframework.aop.config.internalAutoProxyCreator 的作用
C- AopConfigUtils # String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator"
?- 內(nèi)部管理的自動(dòng)代理創(chuàng)建器的bean名
復(fù)制代碼總結(jié)
講道理 , 這篇文章其實(shí)沒(méi)寫(xiě)好 , 很多地方現(xiàn)在都沒(méi)弄清楚 , 精力有限無(wú)法在細(xì)致深入 , 總得來(lái)說(shuō)算是一個(gè)半成品吧 , 后面時(shí)間充裕了 , 再來(lái)深入看一下
核心概念 :
AbstractAutoProxyCreator # createProxy 發(fā)起代理類(lèi)的創(chuàng)建
AutoProxyUtils 為工具類(lèi) , 用于原類(lèi)和代理的一些常見(jiàn)操作處理
通過(guò) AopProxyFactory 創(chuàng)建代理類(lèi) , 有2種 : ObjenesisCglibAopProxy / JdkDynamicAopProxy
作者:AntBlack
鏈接:https://juejin.cn/post/6980187257856589855
來(lái)源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。
