Spring AOP中如何为Bean创建代理?
在[Spring AOP使用(踩坑)实践总结](https://janus.blog.csdn.net/article/details/69485899)及[IOC容器的依赖注入详解](https://janus.blog.csdn.net/article/details/78264703)我们提到过,当Bean实例化过程中会触发BeanPostProcessor的动作。其中AbstractAut
前置博文:
Spring AOP中如何为Bean创建代理?
Spring AOP中是如何注册Advisor的?
Spring AOP如何为目标方法创建拦截器链?
Spring AOP拦截器调用的实现
Spring AOP中CGLIB代理对象增强通知执行原理
在Spring AOP使用(踩坑)实践总结及IOC容器的依赖注入详解我们提到过,当Bean实例化过程中会触发BeanPostProcessor
的动作。其中 AbstractAutoProxyCreator
的postProcessAfterInitialization
方法(这个方法在initializeBean方法中触发) 中我们可以看到其会尝试对Bean进行代理。
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 获取缓存key
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 如果earlyProxyReferences中不存在 {cacheKey,bean},执行wrapIfNecessary
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
本文我们尝试分析Spring AOP如何对bean进行包装代理的。假设我们定义了切片如下所示:
@Aspect
@Component
public class LogAspect {
@Pointcut("execution(* com.recommend.controller.*.*(..))")
public void logPointCut() {
}
@Before(value = "execution(* com.recommend.controller.*.*(..))")
public void beforeMethod(JoinPoint point) {
System.out.println(" before(Joinpoint point)");
}
@After("logPointCut()")
public void afterMethod(JoinPoint point) {
System.out.println(" afterMethod(Joinpoint point)");
}
@AfterReturning(pointcut = "logPointCut()",returning="result")
public void AfterReturning(JoinPoint point,Object result) {
System.out.println(" AfterReturning(Joinpoint point)");
}
@AfterThrowing(value = "logPointCut()",throwing="exception")
public void AfterThrowing(JoinPoint point,Exception exception) {
System.out.println(" AfterThrowing(Joinpoint point)");
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
long beginTime = System.currentTimeMillis();
// 执行方法
Object result = point.proceed();
// 执行时长(毫秒)
long time = System.currentTimeMillis() - beginTime;
//异步保存日志
return result;
}
}
接下来我们来看AbstractAutoProxyCreator
的wrapIfNecessary
方法。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果当前bean有自定义targetSource,直接返回
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 如果当前bean无需代理,直接返回
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//如果当前bean是Advice、Pointcut、Advisor或者AopInfrastructureBean可以直接返回
//如果当前bean是original instance,那么也直接返回,如XXXX.ORIGINAL 命名的bean
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
// DO_NOT_PROXY=null
//如果没有specificInterceptors ,则不创建代理
if (specificInterceptors != DO_NOT_PROXY) {
// 保存代理标志 Map<Object, Boolean> advisedBeans
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
// Map<Object, Class<?>> proxyTypes 保存代理类型
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 走到这里说明无需创建代理
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
从上面方法我们可以看到,如果当前bean拥有advice,也就是我们定义的切面表达式拦截了当前bean的某个方法,那么就会尝试创建代理并在advisedBeans存储代理标志。
这里有这样关键的两步:
- getAdvicesAndAdvisorsForBean获取advice
- createProxy,创建代理
那什么时候不需要对bean进行代理呢?
// targetSourcedBeans包含beanName,也就是bean有custom TargetSource
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;
}
isInfrastructureClass(bean.getClass())
:Advice、Pointcut、Advisor、AopInfrastructureBean或者有@Aspect注解
shouldSkip:XXX.ORIGINAL
格式命名的bean或者该bean是AspectJPointcutAdvisor且aspectName==beanName
【1】getAdvicesAndAdvisorsForBean
我们先看一下获取到的Object[] specificInterceptors
是个什么。如下所示,在这里其获取到是一个advisor数组,每个advisor呢主要有pointcut与advice组成。前者表示连接点,后置表示应用的增强通知。
那么为什么用specificInterceptors命名呢,而且其方法名字是getAdvicesAndAdvisorsForBean。也就是说这里不仅仅是advisor,还可能是advice。
如下所示,在AbstractAutoProxyCreator内部其是一个抽象方法并没有提供实现。
@Nullable
protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
@Nullable TargetSource customTargetSource) throws BeansException;
主要的实现在子类AbstractAdvisorAutoProxyCreator中。
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
这里我们继续看findEligibleAdvisors(beanClass, beanName)
方法。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
// 找到所有的Advisor && this.aspectJAdvisorsBuilder.buildAspectJAdvisors()
List<Advisor> candidateAdvisors = findCandidateAdvisors();
// 为当前bean从候选candidateAdvisors找到可以应用的advisor
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
// 扩展Advisor 如果eligibleAdvisors不为空
//则在首位添加ExposeInvocationInterceptor.ADVISOR
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
// 使用AnnotationAwareOrderComparator进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
第一步,findCandidateAdvisors
方法使用找到容器中的Advisor。
// AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
@Override
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
// 找到所有的Advisor
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
// 这里会触发Advisor的创建 --如我们切面的通知会和poincut一起被保证为advisor
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
// super.findCandidateAdvisors();
//AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
如下图所示,我们自定义的logAspect也在列。
关于Advisor的查找和创建,更多信息可以参考博文:Spring AOP中是如何注册Advisor的?
第二步,findAdvisorsThatCanApply方法从上面得到的候选Advisor中寻找到可以应用到目标Bean的advisor。
// AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
如果当前advisor是IntroductionAdvisor,那么将会得到其ClassFilter然后调用matches方法默认DefaultIntroductionAdvisor
的matches方法是true。
如果是PointcutAdvisor,那么将会获取到Pointcut进而得到MethodMatcher。最终会通过MethodMatcher与目标类的所有方法进行匹配
第三步,extendAdvisors扩展advisor。这是给子类提供的一个扩展钩子,允许子类覆盖该方法并注册额外Advisor。默认实现是空,子类AspectJAwareAdvisorAutoProxyCreator重写了该方法,会尝试在首位添加ExposeInvocationInterceptor.ADVISOR。
//AspectJAwareAdvisorAutoProxyCreator#extendAdvisors
@Override
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
// 如果advisor包含advice且candidateAdvisors没有ExposeInvocationInterceptor.ADVISOR,
// 则尝试将其加入candidateAdvisors
第四步,如果最终eligibleAdvisors 不为空,那么将使用AnnotationAwareOrderComparator进行排序(按照advisor的order值进行排序)。
单个Aspect内部排序后的结果是(从上到下):
AfterThrowing>AfterReturning>After>Around>Before
至此,我们得到了List<Advisor> advisors
,转换为array返回。
【2】创建代理
也就是下面这句代码。
// AbstractAutoProxyCreator#createProxy
Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors,
new SingletonTargetSource(bean));
那么接下来我们分析createProxy这个方法。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
// 记录原始bean 类型,放到关联的beanDefinition的Map<String, Object> attributes中
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
// 创建代理工厂,用来获取AopProxy
ProxyFactory proxyFactory = new ProxyFactory();
// 设置属性 如proxyTargetClass
proxyFactory.copyFrom(this);
// 判断proxyTargetClass,默认为false,
//在实例化时ProxyConfig的proxyTargetClass会被设置为true
// true则意味着目标targetClass非接口时使用CGLIB对bean进行代理
if (!proxyFactory.isProxyTargetClass()) {
//是否代理目标类,这时采用cglib进行代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
// 这时采用JDK动态代理
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
// 从specificInterceptors获取Advisor
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
//设置proxyFactory
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
//提供子类进行重写的,默认为空
customizeProxyFactory(proxyFactory);
// 设置冻结属性,freezeProxy默认为false
proxyFactory.setFrozen(this.freezeProxy);
// 默认为false AbstractAdvisorAutoProxyCreator覆盖该方法返回true
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//根据代理工厂获取具体代理如ObjenesisCglibAopProxy
//然后为bean创建代理对象
return proxyFactory.getProxy(getProxyClassLoader());
}
根据代码来看,首先是为当前beanDefinition记录了bean的原始类型。然后实例化ProxyFactory 对其进行设置如advisors、targetSource、Frozen及PreFiltered。之后使用代理工厂获取具体AopProxy如ObjenesisCglibAopProxy
或者JdkDynamicAopProxy
。根据具体的AopProxy对目标Bean进行代理包装。
那么这里我们着重分析两块:
- buildAdvisors ,解析得到Advisor数组
- proxyFactory.getProxy(getProxyClassLoader());,创建代理对象
① buildAdvisors
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
Advisor[] commonInterceptors = resolveInterceptorNames();
// 如果有公共的拦截器且applyCommonInterceptorsFirst为true,
// 则放在allInterceptors第一个位置
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 {
// 否则直接addAll,不指定位置
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
// 对每一个allInterceptors中的对象进行包装得到Advisor
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
如上代码所示,先尝试得到公共的拦截器,如果有则放到allInterceptors中。然后对对每一个allInterceptors中的对象进行包装得到Advisor。
这里我们解释一下拦截器。在前面源码我们可以看到诸多xxxxInterceptor命名的变量,这个其实和我们通常理解的Interceptor接口不一样,这里是业务含义指拦截方法处理前后进行增强通知,具体的bean可能是
InstantiationModelAwarePointcutAdvisorImpl
或者ExposeInvocationInterceptor.ADVISOR
。
我们继续往下看DefaultAdvisorAdapterRegistry是如何对adviceObject进行包装返回Advisor的。
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);
}
方法解释如下:
- ① 如果是Advisor,直接返回;
- ② 如果不是Advice,抛出异常UnknownAdviceTypeException
- ③ 如果是MethodInterceptor,返回DefaultPointcutAdvisor;
- ④ 尝试返回DefaultPointcutAdvisor
- ⑤ 抛出异常DefaultPointcutAdvisor
默认在构建DefaultAdvisorAdapterRegistry实例时注册了三个适配器。
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
至此我们解析得到了Advisor,就可以交给ProxyFactory创建代理了。
② proxyFactory.getProxy
如下所示ProxyFactory的getProxy方法。
// ProxyFactory#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
这里最终会走两个分支:JdkDynamicAopProxy和CglibAopProxy。我们先看一下createAopProxy()
ProxyCreatorSupport的createAopProxy方法。
protected final synchronized AopProxy createAopProxy() {
//如果为激活,进行激活
if (!this.active) {
activate();
}
// 这里默认是DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
/**
* Activate this proxy configuration.
*/
private void activate() {
this.active = true; // 设置为true
// 遍历监听,默认情况下不存在AdvisedSupportListener
for (AdvisedSupportListener listener : this.listeners) {
listener.activated(this);
}
}
DefaultAopProxyFactory的createAopProxy得到具体的AopProxy
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
// 如果optimize为true或者proxyTargetClass为true或者 是否有非SpringProxy接口超类
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
// 这里其实是从targetSource中获取targetClass
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.");
}
// 如果targetClass是接口或者其是一个Proxy代理类
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
这里会根据targetClass是类 or 接口返回ObjenesisCglibAopProxy
或者JdkDynamicAopProxy
。
那么接下来就该执行具体的getProxy(classLoader)方法了。
在代理对象的生成过程中,首先要从AdvisedSupport对象中取得配置的目标对象,这个目标对象是实现AOP功能所必需的,如果不存在将直接抛出异常,提醒AOP应用需要提供正确的目标对象的配置。在对目标对象的配置的检查完成以后,需要根据配置的情况来决定用什么方式来创建代理对象。一般而言,默认的方式是使用jdk来产生代理对象。但是遇到的配置的目标对象不是接口类的实现,会使用CGLIB来产生代理对象。
③ JdkDynamicAopProxy创建代理
如下所示,在JdkDynamicAopProxy
中,使用了jdk 的Proxy类来生成代理对象,在生成Proxy对象之前,首先需要从advised对象中取得代理对象的代理接口配置,然后调用Proxy的newProxyInstance
方法,最终得到对应的Proxy代理对象。
在生成代理对象时,需要指明三个参数,一个是类加载器,一个是代理接口,另外一个就是Proxy回调方法所在的对象,这个对象需要实现InvocationHandler
接口。
这个InvocationHandler
接口定义了invoke方法,提供了代理对象的回调入口。对于JdkDynamicAopProxy
,它本身实现了InvocationHandler
接口和invoke方法,这个invoke方法是Proxy代理对象的回调方法,所以可以使用this来把JdkDynamicAopProxy
指派给Proxy对象(也就是说JdkDynamicAopProxy
对象本身)。在Proxy代理的接口方法被调用时,会触发invoke方法的回调,这个回调方法完成了AOP编织实现的封装。
@Override
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);
// 判断接口是否有equals 或者 hashCode方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 生成代理
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
④ CglibAopProxy创建代理
在CglibAopProxy创建代理的过程会为切面拦截的目标类的目标方法创建拦截器链也就是List<?> chain
其实就是MethodInterceptor[]
。然后放到AdvisedSupport的Map<MethodCacheKey, List<Object>> methodCache
中。这样在触发目标方法时候会按照这个拦截器链进行增强。
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
}
try {
// 从advised中取得在IOC容器中配置的target对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
// 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);
}
}
//验证代理对象的接口配置
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
// 创建并配置CGLIB的Enhancer,这个Enhancer对象是CGLIB的主要操作类
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 设置Enhancer对象,包括设置代理接口、回调方法
enhancer.setSuperclass(proxySuperClass);
//设置接口,如SpringProxy Advised
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
// SpringNamingPolicy
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
// 这里是核心,设置回调拦截器,如DynamicAdvisedInterceptor
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.
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);
}
}
在ObjenesisCglibAopProxy中实现了代理实例的创建与回调的设置。
@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
if (objenesis.isWorthTrying()) {
try {
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
}
catch (Throwable ex) {
logger.debug("Unable to instantiate proxy using Objenesis, " +
"falling back to regular proxy construction", ex);
}
}
if (proxyInstance == null) {
// Regular instantiation via default constructor...
try {
Constructor<?> ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
ReflectionUtils.makeAccessible(ctor);
proxyInstance = (this.constructorArgs != null ?
ctor.newInstance(this.constructorArgs) : ctor.newInstance());
}
catch (Throwable ex) {
throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
"and regular proxy instantiation via default constructor fails as well", ex);
}
}
((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
在这个生成代理对象的过程中,需要注意的是对Enhancer对象callback回调的设置,正是这些回调封装了Spring AOP的实现,就像前面介绍的jdk的proxy对象的invoke回调方法一样。在Enhancer的callback回调设置汇总,实际上是通过设置DynamicAdvisedInterceptor拦截器来完成AOP功能的。
作为AOP实现的一部分,对target目标对象的方法调用会首先被AOPProxy代理对象拦截,对于不同的AopProxy代理对象的生成方式,会使用不同的拦截回调入口。例如对于jdk的代理对象,使用的是InvocationHandler的invoke回调入口。对于CGLIB的代理对象,使用的是设置好的callback回调。在这些callback回调中,对于AOP实现是通过DynamicAdvisedInterceptor来完成的,而其回调入口是intercept方法。
【3】AOP两种代理
Spring 提供了两种方式来生成代理对象: JDKProxy 和 Cglib,具体使用哪种方式生成由AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。默认的策略是如果目标类是接口,则使用JDK 动态代理技术,否则使用 Cglib 来生成代理。
① JDK动态接口代理
JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。
InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类的代码,动态将横切逻辑和业务逻辑编制在一起。Proxy 利用 InvocationHandler 动态创建一个符合某一接口的实例,生成目标类的代理对象。
JDK动态代理只能为接口创建动态代理实例,而不能对类创建动态代理。需要获得被目标类的 接口信息(应用Java的反射技术),生成一个实现了代理接口的动态代理类(字节码),再通过 反射机制获得动态代理类的构造函数,利用构造函数生成动态代理类的实例对象,在调用具体方法前调用invokeHandler方法来处理。
② CGLib 动态代理
CGLib 全称为 Code Generation Library,是一个强大的高性能,高质量的代码生成类库,可以在运行期扩展 Java 类与实现 Java 接口,CGLib 封装了 asm,可以在运行期动态生成新的 class。CGLib动态代理需要依赖asm包,把被代理对象类的class文件加载进来,修改其字节码生成 子类
JDK 创建代理有一个限制,就是只能为接口创建代理实例,而对于没有通过接口定义业务方法的类,则可以通过 CGLib 创建动态代理。
更多推荐
所有评论(0)