当前位置: 首页 > news >正文

东莞建站网站石家庄网站建设解决方案

东莞建站网站,石家庄网站建设解决方案,广州网站制作功能,网页 调用 wordpressSpring Configuration 和 Component 区别 一句话概括就是 Configuration 中所有带 Bean 注解的方法都会被动态代理#xff0c;因此调用该方法返回的都是同一个实例。 下面看看实现的细节。 Configuration 注解#xff1a; Target(ElementType.TYPE) Retention(RetentionPol…Spring Configuration 和 Component 区别 一句话概括就是 Configuration 中所有带 Bean 注解的方法都会被动态代理因此调用该方法返回的都是同一个实例。 下面看看实现的细节。 Configuration 注解 Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) Documented Component public interface Configuration {String value() default ; }从定义来看 Configuration 注解本质上还是 Component因此 或者 ComponentScan 都能处理Configuration 注解的类。 Configuration 标记的类必须符合下面的要求 配置类必须以类的形式提供不能是工厂方法返回的实例允许通过生成子类在运行时增强cglib 动态代理。配置类不能是 final 类没法动态代理。配置注解通常为了通过 Bean 注解生成 Spring 容器管理的类配置类必须是非本地的即不能在方法中声明不能是 private。任何嵌套配置类都必须声明为static。Bean 方法可能不会反过来创建进一步的配置类也就是返回的 bean 如果带有 Configuration也不会被特殊处理只会作为普通的 bean。 加载过程 Spring 容器在启动时会加载默认的一些 PostPRocessor其中就有 ConfigurationClassPostProcessor这个后置处理程序专门处理带有 Configuration 注解的类这个程序会在 bean 定义加载完成后在 bean 初始化前进行处理。主要处理的过程就是使用 cglib 动态代理增强类而且是对其中带有 Bean 注解的方法进行处理。 在 ConfigurationClassPostProcessor 中的 postProcessBeanFactory 方法中调用了下面的方法 /*** Post-processes a BeanFactory in search of Configuration class BeanDefinitions;* any candidates are then enhanced by a {link ConfigurationClassEnhancer}.* Candidate status is determined by BeanDefinition attribute metadata.* see ConfigurationClassEnhancer*/ public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {MapString, AbstractBeanDefinition configBeanDefs new LinkedHashMapString, AbstractBeanDefinition();for (String beanName : beanFactory.getBeanDefinitionNames()) {BeanDefinition beanDef beanFactory.getBeanDefinition(beanName);if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {//省略部分代码configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);}}if (configBeanDefs.isEmpty()) {// nothing to enhance - return immediatelyreturn;}ConfigurationClassEnhancer enhancer new ConfigurationClassEnhancer();for (Map.EntryString, AbstractBeanDefinition entry : configBeanDefs.entrySet()) {AbstractBeanDefinition beanDef entry.getValue();// If a Configuration class gets proxied, always proxy the target classbeanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);try {// Set enhanced subclass of the user-specified bean classClass? configClass beanDef.resolveBeanClass(this.beanClassLoader);Class? enhancedClass enhancer.enhance(configClass, this.beanClassLoader);if (configClass ! enhancedClass) {//省略部分代码beanDef.setBeanClass(enhancedClass);}}catch (Throwable ex) {throw new IllegalStateException(Cannot load configuration class: beanDef.getBeanClassName(), ex);}} }在方法的第一次循环中查找到所有带有 Configuration 注解的 bean 定义然后在第二个 for 循环中通过下面的方法对类进行增强 Class? enhancedClass enhancer.enhance(configClass, this.beanClassLoader);然后使用增强后的类替换了原有的 beanClass beanDef.setBeanClass(enhancedClass);所以到此时所有带有 Configuration 注解的 bean 都已经变成了增强的类。 下面关注上面的 enhance 增强方法多跟一步就能看到下面的方法 /*** Creates a new CGLIB {link Enhancer} instance.*/ private Enhancer newEnhancer(Class? superclass, ClassLoader classLoader) {Enhancer enhancer new Enhancer();enhancer.setSuperclass(superclass);enhancer.setInterfaces(new Class?[] {EnhancedConfiguration.class});enhancer.setUseFactory(false);enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));enhancer.setCallbackFilter(CALLBACK_FILTER);enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());return enhancer; }通过 cglib 代理的类在调用方法时会通过 CallbackFilter 调用这里的 CALLBACK_FILTER 如下 // The callbacks to use. Note that these callbacks must be stateless. private static final Callback[] CALLBACKS new Callback[] {new BeanMethodInterceptor(),new BeanFactoryAwareMethodInterceptor(),NoOp.INSTANCE };private static final ConditionalCallbackFilter CALLBACK_FILTER new ConditionalCallbackFilter(CALLBACKS);其中 BeanMethodInterceptor 匹配方法如下 Override public boolean isMatch(Method candidateMethod) {return BeanAnnotationHelper.isBeanAnnotated(candidateMethod); }//BeanAnnotationHelper public static boolean isBeanAnnotated(Method method) {return AnnotatedElementUtils.hasAnnotation(method, Bean.class); }也就是当方法有 Bean 注解的时候就会执行这个回调方法。 另一个 BeanFactoryAwareMethodInterceptor 匹配的方法如下 Override public boolean isMatch(Method candidateMethod) {return (candidateMethod.getName().equals(setBeanFactory) candidateMethod.getParameterTypes().length 1 BeanFactory.class candidateMethod.getParameterTypes()[0] BeanFactoryAware.class.isAssignableFrom(candidateMethod.getDeclaringClass())); }当前类还需要实现 BeanFactoryAware 接口上面的 isMatch 就是匹配的这个接口的方法。 Bean 注解方法执行策略 先给一个简单的示例代码 Configuration public class MyBeanConfig {Beanpublic Country country(){return new Country();}Beanpublic UserInfo userInfo(){return new UserInfo(country());}} 相信大多数人第一次看到上面 userInfo() 中调用 country() 时会认为这里的 Country 和上面 Bean 方法返回的 Country 可能不是同一个对象因此可能会通过下面的方式来替代这种方式 Autowired private Country country;实际上不需要这么做后面会给出需要这样做的场景直接调用 country() 方法返回的是同一个实例。 下面看调用 country() 和 userInfo() 方法时的逻辑。 现在我们已经知道 Configuration 注解的类是如何被处理的了现在关注上面的 BeanMethodInterceptor看看带有 Bean 注解的方法执行的逻辑。下面分解来看 intercept 方法。 //首先通过反射从增强的 Configuration 注解类中获取 beanFactory ConfigurableBeanFactory beanFactory getBeanFactory(enhancedConfigInstance);//然后通过方法获取 beanName默认为方法名可以通过 Bean 注解指定 String beanName BeanAnnotationHelper.determineBeanNameFor(beanMethod);//确定这个 bean 是否指定了代理的范围 //默认下面 if 条件 false 不会执行 Scope scope AnnotatedElementUtils.findMergedAnnotation(beanMethod, Scope.class); if (scope ! null scope.proxyMode() ! ScopedProxyMode.NO) {String scopedBeanName ScopedProxyCreator.getTargetBeanName(beanName);if (beanFactory.isCurrentlyInCreation(scopedBeanName)) {beanName scopedBeanName;} }//中间跳过一段 Factorybean 相关代码//判断当前执行的方法是否为正在执行的 Bean 方法 //因为存在在 userInfo() 方法中调用 country() 方法 //如果 country() 也有 Bean 注解那么这个返回值就是 false. if (isCurrentlyInvokedFactoryMethod(beanMethod)) {// 判断返回值类型如果是 BeanFactoryPostProcessor 就写警告日志if (logger.isWarnEnabled() BeanFactoryPostProcessor.class.isAssignableFrom(beanMethod.getReturnType())) {logger.warn(String.format(Bean method %s.%s is non-static and returns an object assignable to Springs BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as Autowired, Resource and PostConstruct within the methods declaring Configuration class. Add the static modifier to this method to avoid these container lifecycle issues; see Bean javadoc for complete details.,beanMethod.getDeclaringClass().getSimpleName(), beanMethod.getName()));}//直接调用原方法创建 beanreturn cglibMethodProxy.invokeSuper(enhancedConfigInstance, beanMethodArgs); } //如果不满足上面 if也就是在 userInfo() 中调用的 country() 方法 return obtainBeanInstanceFromFactory(beanMethod, beanMethodArgs, beanFactory, beanName); 关于 isCurrentlyInvokedFactoryMethod 方法 可以参考 SimpleInstantiationStrategy 中的 instantiate 方法这里先设置的调用方法 currentlyInvokedFactoryMethod.set(factoryMethod); return factoryMethod.invoke(factoryBean, args);12 而通过方法内部直接调用 country() 方法时不走上面的逻辑直接进的代理方法也就是当前的 intercept方法因此当前的工厂方法和执行的方法就不相同了。 obtainBeanInstanceFromFactory 方法比较简单就是通过 beanFactory.getBean 获取 Country如果已经创建了就会直接返回如果没有执行过就会通过 invokeSuper 首次执行。 因此我们在 Configuration 注解定义的 bean 方法中可以直接调用方法不需要 Autowired 注入后使用。 Component 注意 Component 注解并没有通过 cglib 来代理Bean 方法的调用因此像下面这样配置时就是两个不同的 country。 Component public class MyBeanConfig {Beanpublic Country country(){return new Country();}Beanpublic UserInfo userInfo(){return new UserInfo(country());}}有些特殊情况下我们不希望 MyBeanConfig 被代理代理后会变成WebMvcConfig$$EnhancerBySpringCGLIB$$8bef3235293时就得用 Component这种情况下上面的写法就需要改成下面这样 Component public class MyBeanConfig {Autowiredprivate Country country;Beanpublic Country country(){return new Country();}Beanpublic UserInfo userInfo(){return new UserInfo(country);}}这种方式可以保证使用的同一个 Country 实例。
http://www.yutouwan.com/news/396029/

相关文章:

  • 建站资源云南省建设厅官方网站不良记录
  • 手机怎么做弹幕小视频网站重庆最新新闻事件
  • 给别人做网站怎么建设网站商城
  • 哪些网站可以用来做百科参考广州注册公司名称
  • 南宁做网站费用软件开发步骤流程
  • 如何把图片做网站背景网站设计制作公司地址
  • 网站优化怎样提高网站用户体验路由下做网站映射
  • 娱乐公司网站建设价格怎么注册公司名称
  • 淘宝客 网站备案本地wordpress环境
  • 外贸模板网站seo外包公司多吗
  • 网站的主题定位wordpress.org移除
  • 网站全面详细创建步骤网站建设存在问题
  • 企业网站的特点公众号外链网站怎么做
  • dz门户网站模板个体工商户未做年报会罚款吗
  • 百度认证官方网站公司网站建设费用入什么费用
  • 设计素材网站哪个最好用昆明软件开发公司
  • 电子商务和网站开发 职务网站建设规划大纲
  • 东莞网站建设基本流程图网站如何做360度全景
  • 如何规划网站栏目商店网站制作
  • 宁波企业网站开发公司h5前端开发主要做什么
  • 网站的按钮怎么做的网站发布与推广怎么写
  • jrs直播网站谁做的sns网站建设
  • 做关于什么内容的网站备案网查询化妆品
  • 炫酷一些的网站自动下单网站开发
  • 大气网站图私人app一键制作器软件
  • wordpress绑定域名企业网站排名软件度智能优化
  • 自建房设计网站推荐为什么网站的备案号在备案网站查询不到
  • 无锡电子商务网站制作wordpress改 cms
  • 佛山网站哪家最专业discuz应用中心打不开
  • 做学校子网站网站建设属于会计的什么科目