highlight: arduino-light
在spring aop中,如果我们的类属符合如下条件:被切面的pointcut匹配到、或者属于自定义的Advisor接口实现类,那么spring在bean完成实例化之后,会为类生成代理对象。这是众所周知的aop流程。
此外,spring还为我们提供了TargetSourceCreator接口,该接口的功能是:在bean实例化之前,就为类生成代理。 现在我们通过查看源码的方式,来了解该接口的功能。
创建代理
doGetBean
在循环依赖中我们讲了spring实例化bean的入口,refresh->finishBeanFactoryInitialization->preInstantiateSingletons->getBean->doGetBean,看doGetBean中的如下代码
java if (mbd.isSingleton()) { // 实例化bean sharedInstance = getSingleton(beanName, () -> { try { // 真正的完成bean的创建 return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
createBean
createBean(beanName, mbd, args);方法真正的完成了bean的实例化,包括循环依赖、AOP、生命周期等。
所谓的AOP无非就是将bean加强,在bean的方法前后加上其他的方法而已,bean的class在虚拟机启动的时候就加载到JVM里了,我们不会通过修改class来动态扩展bean的功能,但是可以新生成一个类(动态代理类),这个类呢,包含了bean的所有功能,同时又进行了加强,然后将这个动态代理类实例化,替换掉原有的bean,最后放到spring单例池中。
如果你的类没有被其他类依赖,那么可以在doCreateBean之前就创建好代理对象。
java //给Bean后置处理器一个机会,返回一个替代目标对象的代理对象。 //就在这里 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { //注意如果有 InstantiationAwareBeanPostProcessor类型的接口 //并返回了自定义对象 这里会直接返回 return bean; } //如果上面直接返回了bean 下面的doCreateBean就不会执行 Object beanInstance = doCreateBean(beanName, mbdToUse, args);
注意此时还没后面的bean初始化代码,这里AOP的准备工作,AOP实现是靠BeanPostProcessor后置处理器完成的。
BeanFactoryPostProcessor和BeanPostProcessors两者有啥区别?
BeanFactoryPostProcessor干预BeanDefinition的生成,而BeanPostProcessors干预bean的实例化。
java // 给Bean后置处理器一个机会,返回一个替代目标对象的代理对象。 @Nullable protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; //如果尚未被解析 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { //调用InstantiationAwareBeanPostProcessor的 //postProcessBeforeInstantiation //参数是Class bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); //这里返回的是null if (bean != null) { //调用BeanPostProcessor的 postProcessAfterInitialization //注意是BeanPostProcessor bean = applyBeanPostProcessorsAfterInitialization (bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
这个resolveBeforeInstantiation()方法的意义到底是什么?
其实很简单,它的意思就是说,如果我们指定了targetSource,那么可以在这里创建一个代理直接返回,就不需要走下边的实例化和初始化阶段了,因为指定了targetSource后,这个bean就由开发人员自己负责完成创建了。而如果没有指定targetSource,那么就按照正常流程往下执行bean的实例化和初始化,说白了就是人家注释上说的:“给你一个返回代理的机会”。
java protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { //for循环,拿到所有的BeanPostProcessors。 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { //判断是InstantiationAwareBeanPostProcessor //强转为InstantiationAwareBeanPostProcessor InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; //调用InstantiationAwareBeanPostProcessor的 //postProcessBeforeInstantiation方法 Object result = ibp.postProcessBeforeInstantiation (beanClass, beanName); if (result != null) { return result; } } } //如果没有实现自定义的InstantiationAwareBeanPostProcessor //这里返回的是null return null; }
注意这里收集到的是InstantiationAwareBeanPostProcessor InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口。如果applyBeanPostProcessorsBeforeInstantiation
方法返回bean不为空,则实例化结束直接返回resolveBeforeInstantiation方法的返回值。不会执行下面的doCreateBean方法。
spring会遍历所有BeanPostProcessor,这么多后置处理器具体生成代理用到的是哪个?
答:AnnotationAwareAspectJAutoProxyCreator。
AnnotationAwareAspectJAutoProxyCreator继承自AbstractAutoProxyCreator。AbstractAutoProxyCreator是InstantiationAwareBeanPostProcessor类型,并且重写了postProcessBeforeInstantiation方法,所以此时进入AbstractAutoProxyCreator的方法,postProcessBeforeInstantiation方法如下:
postProcessBeforeInstantiation
此时生成代理的第一个时机都出现了,在postProcessBeforeInstantiation方法中生成代理
java @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { //advisedBeans是一个集合,用来保存不需要代理的类。比如我们上面定义的切面 //本身是不需要被代理的,还有加了@Configuration注解的Config配置类, //是不需要代理的,Config其实已经被代理了,之前讲过。 if (this.advisedBeans.containsKey(cacheKey)) { return null; } //isInfrastructureClass(beanClass) //判断我们这个业务类是否需要被代理,进入isInfrastructureClass代码 //判断Advice、Pointcut、Advisor是否是beanClass的超类或者超接口 //shouldSkip(beanClass, beanName) //主要是判断beanName不为空且不是original instance //2个条件都是false 说明需要代理 if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { //不需要代理 this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } //这里会做判断 如果 targetSource //如果有自定义TargetSource //将当前beanName放入targetSourcedBeans缓存中,直接走创建代理的分支 //不会走createBean去创建Bean,这里就是给一个机会。 //关于自定义TargetSource这个分支暂时不讲。 TargetSource targetSource = getCustomTargetSource(beanClass, beanName); //一般情况下targetSource为null不会走这个分支 直接返回null //一般情况下targetSource为null不会走这个分支 直接返回null //一般情况下targetSource为null不会走这个分支 直接返回null 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; }
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName))
这行代码就是判断我们这个业务类是否需要被代理,进入isInfrastructureClass代码:
java //判断Advice、Pointcut、Advisor、AopInfrastructureBean //是否是我们的beanClass的超类或者超接口 protected boolean isInfrastructureClass(Class<?> beanClass) { return (super.isInfrastructureClass(beanClass) || (this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass))); }
调用父类的方法
java protected boolean isInfrastructureClass(Class<?> beanClass) { //判断Advice、Pointcut、Advisor、AopInfrastructureBean //是否是beanClass的超类或者超接口 boolean retVal = Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass); return retVal; }
首先会调用父类的方法 class1.isAssignableFrom(class2) 判定此 Class1 对象所表示的类或接口与指定的 Class2 参数所表示的类或接口是否相同,或是否是其超类或超接口。
如果是则返回 true;否则返回 false。
Advice、Pointcut、Advisor等是跟切面相关的,不需要代理。 如果父类方法返回false,继续判断该类是不是一个切面,是切面的话也是不需要被代理的。
shouldSkip(beanClass, beanName)是判断beanName不为空且不是original instance。
如果2个条件都是false才会被代理 符合条件的放入advisedBeans 集合中,后面会根据这个集合判断业务类是否需要被代理。
上面只是判断是否需要代理。如果是不需要代理的class加入不需要代理的Map集合中。
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
getCustomTargetSource(beanClass, beanName);
一般情况下targetSource为null。
targetSource为null直接返回null的话就不会提前创建代理了。也就是说getCustomTargetSource方法如果返回TargetSource类型,那么if逻辑里会将当前bean加入this.targetSourcedBeans.add(beanName);
并且为当前类生成代理,那么getCustomTargetSource方法逻辑是什么呢?我们进去看看
```java @Nullable protected TargetSource getCustomTargetSource(Class> beanClass, String beanName) {
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.isTraceEnabled()) { logger.trace("TargetSourceCreator [" + tsc + "] found custom TargetSource for bean with name '" + beanName + "'"); } return ts; } } }
// No custom TargetSource found. return null; } ```
先看第一个判断this.customTargetSourceCreators != null
,首先要知道this是谁?
this是AbstractAutoProxyCreator,customTargetSourceCreators是他的属性
AbstractAutoProxyCreator暴露了一个方法
setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators)
总结一下:那也就是说如果我们想要在bean实例化之前,就为类生成代理。我们需要调用 AbstractAutoProxyCreator#setCustomTargetSourceCreators
来设置TargetSourceCreator。
继续往下看
如果customTargetSourceCreators成员有值,于是遍历该成员。
调用TargetSourceCreator#getTargetSource
方法,方法逻辑如下
```java @Override @Nullable public final TargetSource getTargetSource(Class> beanClass, String beanName) { //此处是模板模式会调用到AbstractBeanFactoryBasedTargetSourceCreator的具体子类方法中, //具体子类方法会返回TargetSource AbstractBeanFactoryBasedTargetSource targetSource = createBeanFactoryBasedTargetSource(beanClass, beanName); if (targetSource == null) { return null; }
if (logger.isDebugEnabled()) { logger.debug("Configuring AbstractBeanFactoryBasedTargetSource: " + targetSource); }
//拷贝1个新的internalBeanFactory DefaultListableBeanFactory internalBeanFactory = getInternalBeanFactoryForBean(beanName);
// We need to override just this bean definition, as it may reference other beans // and we're happy to take the parent's definition for those. // Always use prototype scope if demanded. BeanDefinition bd = this.beanFactory.getMergedBeanDefinition(beanName); GenericBeanDefinition bdCopy = new GenericBeanDefinition(bd); if (isPrototypeBased()) { bdCopy.setScope(BeanDefinition.SCOPE_PROTOTYPE); } internalBeanFactory.registerBeanDefinition(beanName, bdCopy);
// Complete configuring the PrototypeTargetSource. targetSource.setTargetBeanName(beanName); //设置拷贝的internalBeanFactory到targetSource targetSource.setBeanFactory(internalBeanFactory);
return targetSource; } ```
AbstractBeanFactoryBasedTargetSourceCreator类是TargetSourceCreator接口的一个抽象实现类。 createBeanFactoryBasedTargetSource(beanClass, beanName);
是标准的模板模式。
createBeanFactoryBasedTargetSource(beanClass, beanName);
会调用到AbstractBeanFactoryBasedTargetSourceCreator的具体子类方法中,返回TargetSource。
接着往下看getInternalBeanFactoryForBean(beanName);
创建一个新的BeanFactory,新的BeanFactory会拥有老的BeanFactory的属性。但需要注意的是,新BeanFactory的BeanPostProcessor集合里,去除了AbstractAutoProxyCreator类型,如下
java protected DefaultListableBeanFactory getInternalBeanFactoryForBean(String beanName) { synchronized (this.internalBeanFactories) { DefaultListableBeanFactory internalBeanFactory=this.internalBeanFactories.get(beanName); if (internalBeanFactory == null) { internalBeanFactory = buildInternalBeanFactory(this.beanFactory); this.internalBeanFactories.put(beanName, internalBeanFactory); } return internalBeanFactory; } }
```java protected DefaultListableBeanFactory buildInternalBeanFactory(ConfigurableBeanFactory containingFactory) { // Set parent so that references (up container hierarchies) are correctly resolved. DefaultListableBeanFactory internalBeanFactory = new DefaultListableBeanFactory(containingFactory);
// 拷贝所有的BeanPostProcessor internalBeanFactory.copyConfigurationFrom(containingFactory);
//排除了AOP核心组件对应的BeanPostProcessor internalBeanFactory.getBeanPostProcessors().removeIf(beanPostProcessor -> beanPostProcessor instanceof AopInfrastructureBean);
return internalBeanFactory; } ```
我们可以看到是克隆一个原来的BeanFactory
出来,然后将里面所有的AopInfrastructureBean
组件都进行移除,而这个组件是什么?其实就是我们的AOP
的核心组件,相当于就是将克隆出来的BeanFactory
当中的所有AOP
的组件全部remove
掉。
参考链接:https://ac.nowcoder.com/discuss/826829?type=1&order=3&pos=26&page=1
到此,类的代理对象就生成了,克隆出来的BeanFactory
当中的所有AOP
的组件被全部remove
掉。所以之后的spring的实例化逻辑也不会生成代理了。
总结一下:如果我们想要在bean实例化之前,就为类生成代理,需要提供AbstractBeanFactoryBasedTargetSourceCreator的实现类。
调用代理对象方法
假设生成的是jdk代理。当调用对象方法时,会进入invoke方法。方法首先获取TargetSource对象
```java @Override @Nullable public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object oldProxy = null; boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
//调用getTarget获取原来的对象
target = targetSource.getTarget();
}
```
调用targetSource.getTarget();
获取原来的对象.
在前言里提到的aop流程中,最终生成的TargetSource是SingletonTargetSource类型,于是获取到的target就是原来的对象。
而在上述流程中,我们是提前生成代理的,生成的TargetSource类型是我们钩子方法里自定义的,所以获取到的target取决于我们如何实现。
总结一下:如果我们想要在bean实例化之前,就为类生成代理,还需要提供TargetSource接口的实现。
下面我们自己来实现TargetSource相关接口。
使用TargetSource提前创建代理
日志接口
```java package target.source;
import org.springframework.stereotype.Component;
@Component public interface LogService {
void print();
} ```
日志接口实现类
```java package target.source;
import org.springframework.stereotype.Component;
@Component public class AopLog implements LogService {
public String log() { System.out.println("----log----"); return "log"; }
@Override public void print() { System.out.println("----print----"); } } ```
配置类
```java package target.source;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.EnableAspectJAutoProxy;
@EnableAspectJAutoProxy(proxyTargetClass = false) @ComponentScan() public class BeanConfig {
} ```
切面和切面表达式
```java package target.source;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.core.PriorityOrdered; import org.springframework.stereotype.Component;
@Aspect @Component public class Aop implements PriorityOrdered {
//指定切入点表达式,拦截那些方法,即为那些类生成代理对象
//@Pointcut("execution(* com.bie.aop.UserDao.save(..))") ..代表所有参数
//@Pointcut("execution(* com.bie.aop.UserDao.*())") 指定所有的方法
//@Pointcut("execution(* com.bie.aop.UserDao.save())") 指定save方法
@Pointcut("execution(* aop.*.*(..))")
public void pointCut(){
}
@Before("pointCut()")
public void Before(){
System.out.println("Before");
}
@After("pointCut()")
public void After(){
System.out.println("After");
}
@AfterThrowing("pointCut()")
public void AfterThrowing(){ System.out.println("AfterThrowing"); }
@AfterReturning("pointCut()") public void AfterReturning(){ System.out.println("AfterReturning"); }
@Around("pointCut()") public void Around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("Around Before"); joinPoint.proceed(); System.out.println("Around After"); }
@Override public int getOrder() { return 1; } } ```
根据上面的总结:如果我们想要在bean实例化之前,就为类生成代理:
1.需要提供AbstractBeanFactoryBasedTargetSourceCreator的实现类
2.需要提供TargetSource接口的实现。
3.需要调用 AbstractAutoProxyCreator#setCustomTargetSourceCreators
来设置TargetSourceCreator。
下面就是开始做这些事情。
CustomTargetSourceCreator
1.需要提供AbstractBeanFactoryBasedTargetSourceCreator的实现类
```java package target.source;
import org.springframework.aop.framework.autoproxy.target.AbstractBeanFactoryBasedTargetSourceCreator; import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class CustomTargetSourceCreator extends AbstractBeanFactoryBasedTargetSourceCreator {
@Override
protected AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(Class<?> beanClass, String beanName) {
if (getBeanFactory() instanceof ConfigurableListableBeanFactory) {
if(beanClass.isAssignableFrom(AopLog.class)) {
return new CustomTargetSource();
}
}
return null;
}
} ```
CustomTargetSource
2.需要提供TargetSource接口的实现。
```java package target.source;
import org.springframework.aop.target.AbstractBeanFactoryBasedTargetSource;
import java.io.Serializable;
public class CustomTargetSource extends AbstractBeanFactoryBasedTargetSource implements Serializable { private static final long serialVersionUID = 5177019431887513952L;
@Override
public Object getTarget() throws Exception {
//此处获取的BeanFactory是上面拷贝出来的BeanFactory
return getBeanFactory().getBean(getTargetBeanName());
}
} ```
其中getBeanFactory()的值,是上述流程提到的新的BeanFactory。
由于该BeanFactory的BeanPostProcessor没有了AbstractAutoProxyCreator。
所以getBeanFactory().getBean(getTargetBeanName())获取的bean,一定是原生的bean,而不是代理对象。
CustomTargetSourceCreatorBeanPostProcessor
3.需要调用 AbstractAutoProxyCreator#setCustomTargetSourceCreators
来设置TargetSourceCreator。
```java package target.source;
import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.core.PriorityOrdered; import org.springframework.stereotype.Component;
@Component public class CustomTargetSourceCreatorBeanPostProcessor implements BeanPostProcessor, PriorityOrdered, BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public int getOrder() {
return 45;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof AnnotationAwareAspectJAutoProxyCreator) {
AnnotationAwareAspectJAutoProxyCreator creator
= (AnnotationAwareAspectJAutoProxyCreator)bean;
CustomTargetSourceCreator targetSourceCreator
= new CustomTargetSourceCreator();
targetSourceCreator.setBeanFactory(beanFactory);
creator.setCustomTargetSourceCreators(targetSourceCreator);
}
return bean;
}
//这里的BeanFactory是原生的BeanFactory
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
} ```
光写了CustomTargetSourceCreator 还不行,因为它必须作为AbstractAutoProxyCreator类的成员,所以我们需要给AbstractAutoProxyCreator的成员赋值。
此处我们自定义了CustomTargetSourceCreatorBeanPostProcessor。
到此,我们就完成了对StudentServiceImpl类型提前生成代理功能的整合。
参考链接:https://blog.csdn.net/qq_39002724/article/details/112970421