SpringAOP模块初始化过程
2015-12-17 09:03
399 查看
SpringAOP模块初始化过程
SpringAOP模块的初始化过程可以分为如下几个步骤:1,读取配置,生成Advisor、PointCut等信息。
跟SpringAOP的相关标签比较多,我们可以选择任意一种方式声明AOP。如下就使用了三种不同的方式:
<aop:config> <!--切入点,controlller --> <aop:pointcut id="pointcut_test" expression="execution(* com.test.controller..*index(..))" /> <!--在该切入点使用自定义拦截器 ,按照先后顺序执行 --> <aop:advisor pointcut-ref="pointcut_test" advice-ref="methodInvokeInterceptor" /> <aop:aspect ref="aspectInterceptor"> <aop:around method="around" pointcut="execution(* com.test.controller..*index(..))"/> </aop:aspect> </aop:config> <!-- 自动扫描使用了aspectj注解的类 --> <aop:aspectj-autoproxy/>
2,在容器创建bean的过程中进行拦截,使得可以进行“偷梁换柱”替换原来的bean
IoC容器在创建bean的时候会调用各种后置处理器,AOP就是利用这些后置处理器在创建bean的过程中做手脚。声明了步骤1中的配置之后,spring会向容器注册AbstractAutoProxyCreator的一些子类。而AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor接口,其中有两个方法实现了AOP的逻辑。下面是AbstractAutoProxyCreator的两个方法:
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); if (!this.targetSourcedBeans.contains(cacheKey)) { if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) { return null; } if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.nonAdvisedBeans.add(cacheKey); return null; } } // Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { 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; }
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; }
3,生成代理返回给容器
不管上面的哪个方法进行了拦截,都需要调用下面创建代理的方法:
protected Object createProxy( Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); // Copy our properties (proxyTargetClass etc) inherited from ProxyConfig. proxyFactory.copyFrom(this); if (!shouldProxyTargetClass(beanClass, beanName)) { // Must allow for introductions; can't just set interfaces to // the target's interfaces only. Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader); for (Class<?> targetInterface : targetInterfaces) { proxyFactory.addInterface(targetInterface); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(this.proxyClassLoader); }
这里将所有创建代理所需的信息都放入proxyFactory中,然后交给proxyFactory来创建代理。如下:
public Object getProxy(ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
而proxyFactory首先创建aopProxy,创建的逻辑在它的父类ProxyCreatorSupport中
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } return getAopProxyFactory().createAopProxy(this); }
ProxyCreatorSupport所使用的aopProxyFactory为DefaultAopProxyFactory,它的createAopProxy方法如下:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { 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()) { return new JdkDynamicAopProxy(config); } if (!cglibAvailable) { throw new AopConfigException( "Cannot proxy target class because CGLIB2 is not available. " + "Add CGLIB to the class path or specify proxy interfaces."); } return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } }
这个方法决定了使用cglib还是JDK生成代理,如果目标类实现了一个或多个接口则利用JDK生成代理。和cglib不同,JDK生成代理不是目标类的子类,若还按目标类型接收则会报错。如果Controller实现了接口并且做了AOP拦截,则AbstractHandlerMethodMapping在扫描HandlerMethod的时候会跳过生成的Controller代理对象。
相关文章推荐
- Java date format 时间格式化
- 详解Java的Hibernate框架中的set映射集与SortedSet映射
- java 跨域访问问题解决
- java 获取随机数字的三种方法
- MyEclipse或Eclipse中工程的导入和导出
- Eclipse或者MyEclipse—在Eclipse或MyEclipse中的操作(3)
- 设定MyEclipse编辑代码区域文字的大小及非关键字的字体、字形和颜色
- java随机数
- MyEclipse开启服务器时总是进入Debug模式
- MyEclipse中背景颜色的设定
- 如何在MyEclipse 中将工程已经删除的文件恢复过来
- 快速在MyEclipse中打开jsp类型的文件
- 提高MyEclipse启动速度
- #3JAVA面向对象之继承#
- #4JAVA面向对象-多态#
- 集算器用作Java结构化文件计算类库
- Java各个类型变量边界
- 武林秘籍之Spring AOP 切面编程的简单应用
- ubuntu 安装jdk7小结
- java 注解