文章目录

  • ​​摘要​​
  • ​​自定义TargetSourceCreator通过postProcessBeforeInstantiation返回bean代理实例​​
  • ​​自定义demo​​
  • ​​TargetSource实现Aop的源码分析​​
  • ​​创建代理对象处​​
  • ​​代理对象执行处​​
  • ​​总结​​

摘要

  • 前文指出,aop有三个拦截入口,本文首先分析postProcessBeforeInstantiation
  • 在ioc章程中,提到如果postProcessBeforeInstantiation返回实例不为null,便不在执行spring doCreateBean,所以这个入口基本不会走到

自定义TargetSourceCreator通过postProcessBeforeInstantiation返回bean代理实例

自定义demo

原生类

@Service
public class HiAop {
@AAA
public void hiAop(String param) {
System.out.println("hi aop says :" + param);
System.out.println("hi aop says :" + param);
System.out.println("hi aop says :" + param);
}
}

通知

@Aspect
@Component
public class Apset {
@Pointcut("execution(* com.renxl.demo.HiAop.hiAop(..))")
public void join(){
}
@Before("join()")
public void before123(){
System.out.println("before");
}
@After("join()")
public void after123(){
System.out.println("after");
}
}

自定义targetsource 以及targetsourceCreater

public class TargetSourceCreatorImpl extends AbstractBeanFactoryBasedTargetSourceCreator {
对于HiAop这个类 我们采用postProcessBeforeInstantiation实例化
@Override
protected AbstractBeanFactoryBasedTargetSource createBeanFactoryBasedTargetSource(Class<?> beanClass, String beanName) {
if (getBeanFactory() instanceof ConfigurableListableBeanFactory) {
if(beanClass.isAssignableFrom(HiAop.class)) {
return new HiAopTargetSource();
}
}
return null;
}
采用单例还是原型 默认自定义的creater都是多例 其会修改beandefinition 的scope
@Override
protected boolean isPrototypeBased() {
return true;
}
}

public class HiAopTargetSource extends AbstractBeanFactoryBasedTargetSource {
@Override
public Object getTarget() throws Exception {
return getBeanFactory().getBean(getTargetBeanName());
}
}

最后我们将aop的BPP绑上该creater

@Component
public class ProcessAnnotationAwareAspectJAutoProxyCreator implements BeanPostProcessor, Ordered, BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public int getOrder() {
return 0;
}
当AnnotationAwareAspectJAutoProxyCreator实例化的时候 后置处理器为其绑定TargetSourceCreatorImpl
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof AnnotationAwareAspectJAutoProxyCreator) {
AnnotationAwareAspectJAutoProxyCreator autoProxyCreator = (AnnotationAwareAspectJAutoProxyCreator) bean;
TargetSourceCreatorImpl targetSourceCreator = new TargetSourceCreatorImpl();
targetSourceCreator.setBeanFactory(beanFactory);
autoProxyCreator.setCustomTargetSourceCreators(targetSourceCreator);
}
return bean;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}

调用分析: 以上一系列代码仅为了验证以下main方法场景,bean和bean1获取到的实例是不同的
为什么? 因为isPrototypeBased为true 表示HiAop这个类改成原型模式 而不是单例模式;这就是HiAopTargetSource的作用之一

TargetSource的原理是什么?
1 以jdk为例,在实现代理类创建时,以前我们通过InvocationHandler完成切面增强,同时调用原Object实例的目标方法
2 而Aop在构建InvocationHandler【JdkDynamicAopProxy】时,完成拦截方法执行后,并不是直接调用原Object实例的目标方法
而是通过TargetSource获取目标对象实例,在通该过实例调用相应方法

基于这种方式,我们有了一个很强的扩展点,比如以下实现
PrototypeTargetSource 每次获取的原生目标实例不是同一个
SingletonTargetSource 每次获取的原生目标实例是同一个
CommonsPool2TargetSource 构建一个池化的目标对象池,可以重复使用

public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
ConfigurableListableBeanFactory beanFactory = run.getBeanFactory();
HiAop bean = beanFactory.getBean(HiAop.class);
HiAop bean1 = beanFactory.getBean(HiAop.class);
bean.hiAop("hello");
bean1.hiAop("hello");
}
}

TargetSource实现Aop的源码分析

创建代理对象处

BPP 拦截自定义实例化目标代理对象

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
......删除其他代码
根据传入的beanclass和beanname判断能否获取到相关TargetSource [一般获取不到]
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
根据beanfactory内部的顾问信息 构建调用链
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
创建代理
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
不执行自定义代理实现 走doCreateBean流程
return null;
}

代理对象执行处

JdkDynamicAopProxy调用实现,并不是直接调用目标对象,而是通过targetSource获取target进行调用

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
...... 删除大量其他代码便于阅读
获取targetSource
TargetSource targetSource = this.advised.targetSource;
通过targetSource获取target
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
依据通知构建拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
执行方法调用
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
retVal = invocation.proceed();
}
返回值
return retVal;

}

总结

  • 通过demo和源码分析,我们知道了targetSource的作用 ,其核心设计目的是为了增强代理类的扩展性,对目标实例的调用
    不在是简单的目标对象,可以是单例,原型,池化等多种实现方式