`

Spring编程风格(转)

 
阅读更多

代码

1、组件

现在很常见的就是不管如何先定义接口,如下所示:

 

Java代码  收藏代码
  1. package com.sishuok;  
  2.   
  3. public interface Interface {  
  4.     public void sayHello();  
  5. }  

 然后定义实现,真的有必要吗?思考下。

Java代码  收藏代码
  1. package com.sishuok;  
  2.   
  3. public class Impl implements Interface {  
  4.   
  5.     @Override  
  6.     public void sayHello() {  
  7.         System.out.println("hello");  
  8.     }  
  9. }  

Bean用于注入Impl,其实此处是错误的,因为定义了接口,应该注入接口的。

Java代码  收藏代码
  1. package com.sishuok;  
  2.   
  3. public class Bean {  
  4.   
  5.     private Impl impl;  
  6.   
  7.     public Bean() {  
  8.     }  
  9.   
  10.     public Bean(final Impl impl) {  
  11.         this.impl = impl;  
  12.     }  
  13. }  

 

2、需要一个切面

怎么实现无所谓,就是为了生成代理对象,重现问题。

Java代码  收藏代码
  1. package com.sishuok;  
  2.   
  3. public class Aspect {  
  4.   
  5.     public void before() {  
  6.         System.out.println("==before");  
  7.     }  
  8. }  

 

3、 配置文件

Java代码  收藏代码
  1. <bean id="aspect" class="com.sishuok.Aspect"/>  
  2. <aop:config>  
  3.     <aop:aspect ref="aspect">  
  4.         <aop:before method="before" pointcut="execution(* com.sishuok.Impl.*(..))"/>  
  5.     </aop:aspect>  
  6. </aop:config>  
  7.   
  8. <bean id="impl" class="com.sishuok.Impl"/>  
  9.   
  10. <bean id="b" class="com.sishuok.Bean">  
  11.     <constructor-arg name="impl" ref="impl"/>  
  12. </bean>  

配置文件很简单。 一个AOP切面会横切Impl,即生成Impl代理,而Bean会注入Impl。

 

4、测试类

 

测试类很简单,只需要加载配置文件即可。

Java代码  收藏代码
  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. @ContextConfiguration(locations={"classpath:spring-config.xml"})  
  3. public class BeanIT {  
  4.   
  5.     @Autowired  
  6.     private Bean bean;  
  7.   
  8.     @Test  
  9.     public void test() {  
  10.         System.out.println("=hello test");  
  11.     }  
  12. }  

 

整段代码很简单,应该能猜到是嘛问题。 

 

抛出的异常

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'b' defined in class path resource [spring-config.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)

 

这个异常让人疑惑,因为它告诉你说可能是构造器的问题,所以可能把我们带坑里看不到真实问题。

 

主要原因是:

我们实际定义了两个构造器:

1、一个空参的:public Bean() 

2、一个带Impl参数的:public Bean(final Impl impl)

 

如果把第一个构造器删除就会得到真实的异常:

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'b' defined in class path resource [spring-config.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.sishuok.Impl]: Could not convert constructor argument value of type [$Proxy8] to required type [com.sishuok.Impl]: Failed to convert value of type '$Proxy8 implementing com.sishuok.Interface,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised' to required type 'com.sishuok.Impl'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [$Proxy8 implementing com.sishuok.Interface,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [com.sishuok.Impl]: no matching editors or conversion strategy found

 

很明显是注入问题,见到$Proxy8 我们就能猜到是JDK动态代理(这个在《spring的二次代理原因及如何排查》说过),即它不能转换为实际的com.sishuok.Impl,问题很明显了.

 

此处还有另一个问题:关于按照构造器参数名注入时,具体参考《【第三章】 DI 之 3.1 DI的配置使用 ——跟我学spring3》中的构造器注入部分。

 

解决方案

1、要么构造器注入接口,即public Bean(final Interface impl)

2、要么使用CGLIB类代理

 

总结

1、知道自己使用的是啥编程风格:

  • 先定义接口,然后实现;如UserController---->UserService(接口 其实现是UserServiceImpl),这种情况大多数人都使用接口注入即可
  • 我喜欢直接定义实现,如UserController--->UserService(实现),因为这是一个模块内部的操作,干嘛定义接口呢?可扩展?想想自己扩展过吗?如果实在想要可扩展我一般是这样:UserApi UserApiImpl 可参考我的es脚手架

 

2、知道自己使用的啥代理:

  • JDK动态代理 还是 CGLIB代理, 做到心中有数,尽量别混用。当然最保险的方式就是使用CGLIB代理。

 

明确自己的风格,从一而终,不要为了玩玩都用上,Spring已经很庞大且复杂了,,使用Spring出问题最多的就是AOP部分,遇到AOP问题。可参考《请不要再使用低级别的AOP API

 

 

我喜欢

  • 给自己使用的无需定义接口;即一个模块内部的都是封装的,定义接口并不会得到很多好处,变过几次实现?? “优先面向接口编程,而非实现” 不是必须,是优先;
  • 给朋友(第三方)使用的定义接口;即要公开的功能,因为接口就是个契约,就是沟通用的;
  • 优先使用setter注入,除非必要才使用构造器注入;
  • 使用CGLIB代理,这样基本不会出现AOP代理注入不了或一些隐晦的问题;
  • 优先使用Spring提供的XML标签简化功能定义,如<aop:config>、<task:executor>等,而不要使用低层次API;
  • 尽量使用XML风格的事务,而不是注解风格;
  • 按照配置的内容分多配置文件存放配置,不要一股脑的放在一起,就像不分包那样;
  • 可配置部分(如db数据)还是放到XML中,不要什么都注解;
  • 使用Spring profile 或 maven profile分环境测试(如开发环境、测试环境、正式机环境);

官方文档还是要看的,当然刚开始可能比较困难,但是坚持几次以后就轻松了,出问题先看文档,接着翻javadoc,基本能搞定,当然读一读源码对日常开发的调错还是很有帮助的。

 

分享到:
评论

相关推荐

    spring响应式编程实战pdf和markdown

    4. **函数式编程**: 在Spring WebFlux中,你可以使用函数式编程风格来构建Web服务,这使得代码更加简洁且易于测试。通过定义处理器链,你可以轻松地组合和复用处理逻辑。 5. **非阻塞I/O**: 响应式编程的一大优势...

    Spring 整合 Scala 编程【转】

    标题 "Spring 整合 Scala 编程【转】" 暗示了本文将探讨如何在Spring框架中使用Scala语言进行编程。Scala是一种强大的、面向对象且支持函数式编程的编程语言,它与Java虚拟机(JVM)兼容,因此可以无缝集成到Spring...

    Spring编程技术与应用 ppt.zip

    **Spring编程技术与应用** Spring框架是Java开发领域中广泛使用的轻量级开源框架,它以其模块化、灵活的依赖注入(DI)和面向切面编程(AOP)能力而闻名。本教学资源包旨在深入讲解Spring的核心概念和技术,帮助...

    Spring3.X编程技术与应用

    Spring提供了Spring MVC作为构建Web应用的框架,支持RESTful架构风格,通过注解来简化请求映射、处理、参数绑定等。 6.事务管理: Spring框架提供了声明式事务管理的功能,通过Spring的事务抽象,可以实现声明式...

    Spring编程专题

    **Spring编程专题** 在软件开发领域,Spring框架是Java企业级应用开发的首选框架,它以其灵活、高效和模块化的设计赢得了广泛的认可。本专题将深入探讨Spring框架的核心概念、关键特性和实际应用。 1. **Spring...

    Spring3.X编程技术与应用.(丁振凡)

    5. **RESTful Web服务支持**:Spring 3.x版本增强了对RESTful Web服务的支持,使得构建RESTful风格的服务变得更加容易。 6. **异步支持**:Spring 3.x引入了对异步编程的支持,允许开发者轻松地编写非阻塞的代码,...

    spring2.0升级到spring3.0.5的开发包

    Spring框架是Java应用程序开发中的一个核心组件,它提供了一个丰富的IOC(Inversion of Control,控制反转)和AOP(Aspect-Oriented Programming,面向切面编程)功能,使得开发者能够更方便地管理对象和实现模块化...

    Spring框架的示例项目源码 Spring Petclinic

    该项目可以帮助开发者理解和学习Spring框架的核心组件,如IoC(Inversion of Control,控制反转)容器、AOP(Aspect Oriented Programming,面向切面编程)、MVC(Model-View-Controller,模型-视图-控制器)架构...

    spring专家编程.rar

    《Spring专家编程》一书是深入理解Spring框架的宝贵资源,尤其对于Java开发人员来说,Spring框架是构建企业级应用的基石。该压缩包包含的"spring专家编程.pdf"文件,很可能是书中某一章节或者全书的电子版,提供了一...

    spring类库 spring类库

    7. **Spring Aspects**:此模块提供了AOP的扩展,支持自定义切面和通知类型,增强了Spring的面向切面编程能力。 8. **Spring WebFlux**:对于反应式编程,Spring WebFlux提供了非阻塞的Web开发模型,适用于高并发和...

    spring-framework-5.3.8

    Spring 框架是 Java 开发领域中广泛使用的开源框架,以其依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)为核心特性,极大地简化了企业级应用的开发工作。5.3.8 版本是 ...

    Spring_Framework_ API_5.0.5 (CHM格式)

    响应式编程提供了另一种编程风格,专注于构建对事件做出响应的应用程序。 SpringFramework5 包含响应流(定义响应性API的语言中立尝试)和 Reactor(由Spring Pivotal团队提供的 Reactive Stream 的Java实现), 以...

    Spring中文API帮助文档

    Spring框架是Java开发中最常用的开源框架之一,它以其强大的依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect-Oriented Programming,简称AOP)能力而闻名。Spring中文API帮助文档是针对Spring框架...

    mybatis-spring-1.31.jar

    这种方式更加灵活,也更符合Spring的编程风格。 在实际应用中,MyBatis-Spring的1.3.1版本修复了一些已知问题,增强了性能,优化了API设计,使得开发者在使用过程中更加顺畅。例如,对于多数据源的支持,以及与...

    spring揭秘 完整带标签

    4. **Spring MVC**:作为Spring的一部分,Spring MVC是一个强大的Web应用框架,用于构建RESTful风格的Web服务。它包含模型、视图和控制器组件,提供了请求处理、视图渲染以及数据绑定等功能。 5. **Spring Boot**:...

    spring-framework-5.3.20

    - **RESTful API**:Spring MVC提供了一套完整的解决方案,用于构建RESTful风格的Web服务。 - **数据库操作**:Spring Data支持多种持久层技术,简化了数据库操作。 - **分布式事务**:Spring的事务管理功能,确保跨...

    Spring 3.1 jar包

    在AOP(面向切面编程)方面,Spring 3.1 提供了对JSR-250注解的完全支持,如@PostConstruct和@PreDestroy,这些注解可以在方法上使用,以便在bean的生命周期中定义初始化和销毁行为。同时,改进了代理模型,支持...

    Spring环境搭建

    也可以使用Java配置类,这更符合现代Spring的编程风格。 6. **启动Spring**:在你的主程序中,你需要创建一个`ApplicationContext`实例,加载配置文件,然后从容器中获取并使用Bean。 7. **测试**:编写单元测试或...

    spring 4.3.29 所有jar包

    4. **Spring MVC**:这是一个强大的Web应用开发模块,提供了模型-视图-控制器架构,支持RESTful风格的URL设计,以及视图解析和异常处理等功能。 5. **Spring Test**:用于测试Spring应用,包括单元测试和集成测试的...

Global site tag (gtag.js) - Google Analytics