得到增强器后,开始着手于创建代理对象,那么首先创建代理工厂。
主要在 AbstractAutoProxyCreator#createProxy,简单工厂模式。
能产生两类对象:CglibAopProxy、JdkDynamicAopProxy。
创建代理工厂,准备创建代理对象所需要的各种资源,具体流程和源码如下:
- 公开需要被代理的对象,在该对象的 BeanDefinition 写入属性 org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass-targetClass
- 新建代理工厂:ProxyFactory,并从当前对象 (AnnotationAwareAspectJAutoProxyCreator,具体看使用注解aop还是xml的aop) 拷贝属性;
- 判断
proxy-target-class属性(TRUE表示强制使用CGLIB代理对象所有的方法):- true
- 判断当前对象是否是JDK代理生成的,如果是把其所有的接口加入ProxyFactory
- false
- 判断是否应该直接代理目标对象,满足下面俩条件的话:就设置 proxyTargetClass=true
- 条件1:beanFactory 是 ConfigurableListableBeanFactory 的实例;
- 条件2:目标bean在IOC中存在,并且其定义中包含上面1中暴露的属性;
- 上面不满足,那么判断是否应该代理目标对象的接口,如果没有符合条件的接口那么设置 proxyTargetClass=true;如果有符合条件的接口,那么把其所有的接口加入ProxyFactory。这里符合条件的接口需要满足三个条件:
- 不容容器内部的接口;
- 不是内部语言接口,比如 xx.cglib.proxy.Factory、xx.bytebuddy.MockAccess;
- 接口中必须有方法。
- 判断是否应该直接代理目标对象,满足下面俩条件的话:就设置 proxyTargetClass=true
- true
- 第3步有很多的判断,主要是为了设置 proxyTargetClass 属性。接下来把并增强的方法包装成 Advisor 数组放到 ProxyFactory 中;和我们目标代理对象也放到 ProxyFactory 中;
- 留给用户扩展点 customizeProxyFactory(proxyFactory);
- 是否需要冻结配置 proxyFactory.setFrozen(this.freezeProxy);
- AbstractAdvisorAutoProxyCreator 将 advisorsPreFiltered() 重写为true;
- 工厂准备完毕,下一步创建 AOP代理对象 proxyFactory.getProxy(getProxyClassLoader());
源码
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {// 如果beanFactory是ConfigurableListableBeanFactory的实例if (this.beanFactory instanceof ConfigurableListableBeanFactory) {// 公开指定需要代理的对象AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);}// 新建代理工厂ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);// 判断是否配置了 <aop:aspectj-autoproxy proxy-target-class="true"/>,表示使用CGLIB实现AOP。默认falseif (proxyFactory.isProxyTargetClass()) {// Explicit handling of JDK proxy targets (for introduction advice scenarios)// 判断当前对象是否是JDK代理生成的// 当Proxy.newProxyInstance方法动态getProxyClass生成为代理类时,返回 true。if (Proxy.isProxyClass(beanClass)) {// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.for (Class<?> ifc : beanClass.getInterfaces()) {proxyFactory.addInterface(ifc);}}} else {// No proxyTargetClass flag enforced, let's apply our default checks...// 判断是否应该代理该对象if (shouldProxyTargetClass(beanClass, beanName)) {proxyFactory.setProxyTargetClass(true);} else {// 评估是否应该代理该对象的接口evaluateProxyInterfaces(beanClass, proxyFactory);}}// 得到增强的拦截方法Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);// 扩展点customizeProxyFactory(proxyFactory);// 冻结配置proxyFactory.setFrozen(this.freezeProxy);// 被子类重写为trueif (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}// 准工作结束,开始创建代理对象return proxyFactory.getProxy(getProxyClassLoader());}
shouldProxyTargetClass
首先判断下 beanFactory 的类型,然后需要判断下 beanDefination了里面的属性值。
protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {return (this.beanFactory instanceof ConfigurableListableBeanFactory &&AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));}
进入 AutoProxyUtils 的方法 shouldProxyTargetClass
判断bean存在,及其其定义中是否包含属性。
public static boolean shouldProxyTargetClass(ConfigurableListableBeanFactory beanFactory, @Nullable String beanName) {if (beanName != null && beanFactory.containsBeanDefinition(beanName)) {BeanDefinition bd = beanFactory.getBeanDefinition(beanName);// 判断BeanDefinition中是否有如下属性// org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClassreturn Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));}return false;}
evaluateProxyInterfaces
判断能否使用 jdk 动态代理。能的话拿到接口,不能的话设置 proxyFactory.setProxyTargetClass(true);
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {// 返回目标对象所有的接口Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());// 是否有符合的代理接口boolean hasReasonableProxyInterface = false;for (Class<?> ifc : targetInterfaces) {// isConfigurationCallbackInterface(ifc) 是否为容器的回调接口// isInternalLanguageInterface(ifc) 是否为内部语言接口// 接口中必须有方法if (!isConfigurationCallbackInterface(ifc)&& !isInternalLanguageInterface(ifc)&& ifc.getMethods().length > 0) {hasReasonableProxyInterface = true;break;}}if (hasReasonableProxyInterface) {// Must allow for introductions; can't just set interfaces to the target's interfaces only.for (Class<?> ifc : targetInterfaces) {proxyFactory.addInterface(ifc);}} else {proxyFactory.setProxyTargetClass(true);}}
