Spring编程注意事项
目录
- Spring Bean定义
- Spring Bean依赖注入
- 1、@Autowired 要求是必须注入的,它先根据类型寻找,如果有多个,这个优先级的决策是先根据 @Primary 来决策,其次是 @Priority 决策,最后是根据 Bean 名字的严格匹配来决策。如果这些帮助决策优先级的注解都没有被使用,名字 也不精确匹配,则返回 null,告知无法决策出哪种最合适
- 2、显式引用 Bean ,需要注意默认bean的名字:如果一个类名是以两个大写字母开 头的,则首字母不变,其它情况下默认首字母变成小写
- 3、引用内部类,默认的bean名字为
- 4、我们一般都会因为 @Value 常用于 String 类型的装配而误 以为 @Value 不能用于非内置对象的装配,实际上这是一个常见的误区
- 5、集合类型的自动注入是 Spring 提供的另外一个强大 功能。
- Spring Bean生命周期
- 1、生命周期:对应实例化 Bean,注入 Bean 依赖,以及初始化 Bean
- 2、使用 @Autowired 直接标记在成 员属性上而引发的装配行为是发生在构造器执行之后的。
- 3、使用 Bean 注解的方法所注册的 Bean 对象,如果用户不设置 destroyMethod 属性,则 其属性值为 AbstractBeanDefinition.INFER_METHOD。此时 Spring 会检查当前 Bean 对象的原始类中是否有名为 shutdown 或者 close 的方法,如果有,此方法会被 Spring 记录下来,并在容器被销毁时自动执行;当然如若没有,那么自然什么都不会发生。
- 4、DefaultListableBeanFactory 类是 Spring Bean 的灵魂,而核心就是其中的 doCreateBean 方法,它掌控了 Bean 实例的创建、Bean 对象依赖的注入、定制类初 始化方法的回调以及 Disposable 方法的注册等全部关键节点。
- Spring AOP
- 1、Spring AOP 的底层是动态代理。而创建代理的方式有两种,JDK 的方式和 CGLIB 的方 式。JDK 动态代理只能对实现了接口的类生成代理,而不能针对普通类。而 CGLIB 是可以 针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,来实现代理对象。
- 2、只有引用的是被动态代理创建出来的对象,才会被 Spring 增强,具备 AOP 该有的功能
- 3、this 调用的当前类方法无法被拦截
- 4、我们一般不能直接从代理类中去拿被代理类的属性,这是因为除非我们显示设置 spring.objenesis.ignore 为 true,否则代理类的属性是不会被 Spring 初始化的,我们 可以通过在被代理类中增加一个方法来间接获取其属性。
- 5、在同一个切面配置中,如果存在多个不同类型的增强,那么其执行优先级是按照增强类 型的特定顺序排列,依次的增强类型为 Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
- 6、在同一个切面配置中,如果存在多个相同类型的增强,那么其执行优先级是按照该增强 的方法名排序,排序方式依次为比较方法名的每一个字母,直到发现第一个不相同且 ASCII 码较小的字母
- 7、“未达到执行顺序预期”的增强方法移动到一个独立的切面类,而不同的切面 类可以使用 @Order 进行修饰。@Order 的 value 值越低,则执行优先级越高。
- Spring事件
- Spring Web
- 1、必须显式在 @RequestParam 中指定请求参数名
- 2、要想到参数类型 的定义到底能不能从请求中自动转化而来
- 3、要完整接收到所有的 Header,不能直接使用 Map 而应该使用 MultiValueMap。常见 的两种方式如下:
- 4、在 HTTP 协议规定中,Header 的名称是无所谓大小写的。但是这并不意味着所有能获 取到 Header 的途径,最终得到的 Header 名称都是统一大小写的。
- 5、不是所有的 Header 在响应中都能随意指定,虽然表面看起来能生效,但是最后返回给 客户端的仍然不是你指定的值。例如,在 Tomcat 下,CONTENT_TYPE 这个 Header 就是这种情况。
- 6、不同的 Body 需要不同的编解码器,而使用哪一种是协商出来的,协商过程大体如下
- 7、不同的编解码器的实现(例如 JSON 工具 Jaskson 和 Gson)可能有一些细节上的不 同,所以你一定要注意当依赖一个新的 JAR 时,是否会引起默认编解码器的改变,从而 影响到一些局部行为的改变。
- 8、在尝试读取 HTTP Body 时,你要注意到 Body 本身是一个流对象,不能被多次读取。
- 9、在很多场景下,我们不一定要寄希望于搜索引擎去区别,只需要 稍微研读下代码,反而更容易理解。例如,对于案例 1,研读完代码后,我们发现它们不 仅可以互换,而且完全可以自定义一个以 @Valid 开头的注解来使用;而对于案例 2,只 能用 @Valid 去开启级联校验。
- 10、不能多次调用 FilterChain#doFilter()。
- 11、在新版本的 Spring Security 中,你一定不要忘记指定一个 PasswordEncoder,因为出于 安全考虑,我们肯定是要对密码加密的
- 12、Spring Security 使用角色相关的授权功能时,你一定要注意这个角色是不是加了前缀 ROLE _。
- Spring事务
- 1、Spring 支持声明式事务机制,它通过在方法上加上 @Transactional,表明该方法需要 事务支持。于是,在加载的时候,根据 @Transactional 中的属性,决定对该事务采取 什么样的策略
- 2、Spring 处理事务的时候,如果没有在 @Transactional 中配置 rollback 属性,那么只有捕获到 RuntimeException 或者 Error 的时候才会触发回滚操作。
- 3、只有当注解为事务的方法被声明为 public 的时候,才会被 Spring 处理。
- 4、在 Spring 声明式的事务处理中,有一个属性 propagation,表示打算对这些方法怎么使 用事务,即一个带事务的方法调用了另一个带事务的方法,被调用的方法它怎么处理自己 事务和调用方法事务之间的关系。
- 5、Spring 事务是可以对多个数据源生效,它提供了一个抽象类 AbstractRoutingDataSource,通过实现这个抽象类,我们可以实现自定义的数据库切换。
- Spring补充
Spring Bean定义
1、Spring默认扫描包(ComponentScan注解)只扫描application所在的包下
而我们可以用显示注解ComponentScans去指定扫描的包,此时默认原来的默认扫描包就被忽略失效了
2、我们定义一个类为 Bean,如果再显式定义了构造器, 那么这个 Bean 在构建时,会自动根据构造器参数定义寻找对应的 Bean(选择参数对应的bean装配),然后反射创建出 这个 Bean。
错例:报找不到对应bean
3、如果定义了多个显示构造器,Spring 无从选择,只能尝试去调用默 认构造器,而这个默认构造器又不存在,就会报错
4、当一个单例的 Bean,使用 autowired 注解标记其属性时,你一定要注意这个属性值会被固定下来。
案例
解决办法
5、注意反射来实例化类
java.lang.Class.newInsance()
java.lang.reflect.Constructor.newInstance()
sun.reflect.ReflectionFactory.newConstructorForSerialization().newInstance()
其中第三种方式不会初始化类属性
Spring Bean依赖注入
1、@Autowired 要求是必须注入的,它先根据类型寻找,如果有多个,这个优先级的决策是先根据 @Primary 来决策,其次是 @Priority 决策,最后是根据 Bean 名字的严格匹配来决策。如果这些帮助决策优先级的注解都没有被使用,名字 也不精确匹配,则返回 null,告知无法决策出哪种最合适
2、显式引用 Bean ,需要注意默认bean的名字:如果一个类名是以两个大写字母开 头的,则首字母不变,其它情况下默认首字母变成小写
3、引用内部类,默认的bean名字为
4、我们一般都会因为 @Value 常用于 String 类型的装配而误 以为 @Value 不能用于非内置对象的装配,实际上这是一个常见的误区
注意要避免和环境变量冲突,也要注意避免和系统变量等其他变量冲突
5、集合类型的自动注入是 Spring 提供的另外一个强大 功能。
Spring Bean生命周期
1、生命周期:对应实例化 Bean,注入 Bean 依赖,以及初始化 Bean
2、使用 @Autowired 直接标记在成 员属性上而引发的装配行为是发生在构造器执行之后的。
报错案例
解决方法
标签:事务,Spring,编程,代理,Bean,注意事项,方法,属性 From: https://www.cnblogs.com/hui7/p/17068285.html