• 为什么@RestController返回的Date类型是Long型


    最近项目中发现一个好玩的事情:本地调试时,返回的date是日期格式yyyy-MM-dd HH:mm:ss,但发布到服务器后就变为Long型的时间戳了 

    最后查到的原因很简单,因为发布服务器启动时的脚本加下如下的参数,而本地没有加

    java -Djava.security.egd=file:/dev/urandom -Dspring.jackson.serialization.write-dates-as-timestamps=true -jar -Xms2048m -Xmx2048m xxx.jar

    就是因为加了这个spring参数,才会使date类型都转变为Long型(除了代码中加如下注解的Date型)

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public Date getCreateDate() {
      return createDate;
    }

    当然,本地如果也想返回Long型时间戳,可以在yml中加上如下配置

    spring.jackson.serialization.write-dates-as-timestamps: true

    但在调查过程中顺便把Spring的一些地方给了解了一遍,总结如下几点

    1. 有关注解

       比如@RestController

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Controller
    @ResponseBody
    public @interface RestController {
    
        /**
         * The value may indicate a suggestion for a logical component name,
         * to be turned into a Spring bean in case of an autodetected component.
         * @return the suggested component name, if any
         * @since 4.0.1
         */
        String value() default "";
    
    }

      回顾下这些常用的注解

      1)元注解

    @Document:是否编入Javadoc
    @Target:使用范围(TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR、PACKAGE等)
    @Retention:保留范围(SOURCE、CLASS、RUNTIME)
    @Inherited:子类继承父类的注解

      2)常用注解

    1. @Autowired和@Qualifier:后者可以根据名称寻找依赖(常用于对同class的多个bean)
    2. 别称:类似@Controller、@Service实质都是Component
    3. @RestController = Controller + ResponseBody
    4. @Transactional(事务控制的注解,很重要)

    于是因为@Transactional想顺便研究下Spring的事务机制...

    2. Spring事务 

      比如@Transactional,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,根据@Transactional 的属性配置信息,这个代理对象决定该声明@Transactional 的目标方法是否由拦截器 TransactionInterceptor 来使用拦截,在 TransactionInterceptor 拦截时,会在在目标方法开始执行之前创建并加入事务,并执行目标方法的逻辑, 最后根据执行情况是否出现异常,利用抽象事务管理器(图 2 有相关介绍)AbstractPlatformTransactionManager 操作数据源 DataSource 提交或回滚事务, 如下图所示。

    这里涉及到的Spring抽象事务管理器AbstractPlatformTransactionManager,实现的是如下接口

    public interface PlatformTransactionManager {
    
        TransactionStatus getTransaction(
                TransactionDefinition definition) throws TransactionException;
    
        void commit(TransactionStatus status) throws TransactionException;
    
        void rollback(TransactionStatus status) throws TransactionException;
    }

    具体底层处理依赖于AbstractPlatformTransactionManager的实现,比如DataSourceTransactionManager管理JDBC的Connection,这些类的关系如下

    @Transactional的使用

    • 属性propagation的使用(通常被称为事务的传播,我认为叫做嵌套事务管理更好) 需要注意下面三种 propagation 可以不启动事务。本来期望目标方法进行事务管理,但若是错误的配置这三种 propagation,事务将不会发生回滚。
      TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
      TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
      TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

      其他选项:
      TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
      TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
      TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
    • 属性rollbackFor
      默认情况出现RuntimeException或者Error才回滚,如果需要定制,则使用rollbackFor(这种情况,如果是自定义异常的父类也会回滚)
    • 属性timeout:如果超过时间未提交成功,则回滚
    • 属性readonly:只读事务(读取期间不会看到中途中其它事务的提交-可重复读)
    • 只有在public方法才有用
    • 自调用问题可以用AspectJ配置解决

    当然,因为这么好用的注解实现又依赖于Spring的AOP,继续...

    3. Spring 的AOP

        简介如下

    AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。
    AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,

       静态代理

    静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强
    实现方法:AspectJ框架
    示例

      动态代理  

    动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
    运行时生成目标类的代理类,该代理类要么与目标类实现相同的接口,要么是目标类的子类
    方法
    1. AspectJ Annotation,但底层依然是Spring AOP,比如@Aspect
    2. 使用CGLIB生成代理类 Enhancer
    3. JDK的动态代理(InvocationHandler)

       Spring AOP 代理有 CglibAopProxy 和 JdkDynamicAopProxy 两种

     参考:

    https://www.jianshu.com/p/e9329c8a59c2

    Spring事务:

    https://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html

    https://www.ibm.com/developerworks/cn/java/j-master-spring-transactional-use/index.html

    Spring的AOP

    https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/index.html

    JDK的动态代理

    https://www.jianshu.com/p/269afd0a52e6

  • 相关阅读:
    for循环中变量的作用域问题
    一个数与0进行按位或,能取整
    Spring中日志的使用(log4j)
    MyBatis实现动态语句操作
    MyBatis实现简单增删改查操作
    python计算2的平方根,并输出小数点后的第100万位数字
    Spring配置文件报错:Multiple annotations found at this line: - Element type "beans" must be followed by either attribute specifications, ">" or "/>". - Start tag of element <beans>
    python跳出多重循环
    python中的生成器(二)
    python中的生成器(一)
  • 原文地址:https://www.cnblogs.com/roostinghawk/p/12080705.html
Copyright © 2020-2023  润新知