豪翔天下

Change My World by Program

0%

Java Spring手册

Spring Initializr:Spring项目初始化工具。

打包

打包成war: mvn clean package

框架分层结构

调用顺序

Controller –> Service Interface –> Service Impl –> Dao Interface –> Dao Impl –> Mapper –> DB

BIZ层

Service(业务逻辑,可以建立子文件夹来进行分类,这样每个biz就可以更细分,如果Biz和Servic都单独作为一层,那么Biz的粒度更细,Service则是提供给别人的接口)、Schedule(定时任务)、Common(一些中间件认证登录等)、Manager、RPC Service、MQTask、JobTask。也有Service和BIZ平行的分层方式,这种情况,一般是Service在调用Biz,Biz执行数据库操作,类似于Manager。

BO(Business Object)

COMMON层

一些公共的对象,公共的抽象类、公共的异常、公共的帮助方法等

DAO层

一般是由MyBatis等工具自动生成的。

DO/PO(Data Object/Persistant Object,与数据表直接对应,也叫Entity层或者Model层):用于存放实体类,与数据库中的属性值保持一致。

Mapper: 对数据库进行数据持久化操作,它的内部方法就是直接对数据库进行操作的。它类似于manager层。可以封装对数据库的复杂的操作。

VO(value object,类似于将数据库的字段抽象为新的业务相关的字段): VO往往用于请求处理层,即Controller。

INTEGRATE层

外部系统的一些接口

Web层

Controller、Config(一些初始化配置,例如线程池、缓存池等配置的初始化)

注解

@Async

  • 必须用在public方法上,同一个类的其他方法调用此方法无法实现异步
  • Spring使用的是SimpleAsyncTaskExecutor来处理@Async注解的任务
1
2
3
4
5
6
7
@EnableAsync
public class MyClass {
@Async
public void testMethod() {
System.out.println("Currently Executing thread name - " + Thread.currentThread().getName());
}
}

Autowired

  • 自动注入,默认按照类型去匹配bean

@Resource

  • Autowired类似,默认按照name去匹配bean
1
2
3
4
public class Post {
@Resource(name = "author")
private Author author;
}

@Service用于标注业务层组件

@Controller用于标注控制层组件(如struts中的action)

@Repository用于标注数据访问组件,即DAO组件

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

重要概念

bean

  • bean有两种初始化方法:

    • applicationContext.xml中直接添加指定的类<bean id="myBean" class="com.MyBean" init-method="initMethod"></bean>
    • 实现InitializingBean接口,并实现afterPropertiesSet方法,这样可以在所有其他的属性设置完成后才初始化该类,如果用上面的方式,则无法实现依赖注入(其他的依赖都还没有初始化)。可以在里面新建一个线程实现启动完成后添加监听线程的功能。
  • 在任意地方获取指定的bean,可以有效解决循环依赖的问题,如下,建立一个方法类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    package com.haofly.net.common.utils;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Component;

    @Component // 一定要加这个
    public class SpringContextUtil implements ApplicationContextAware {
    /**
    * Spring应用上下文环境
    */
    private static ApplicationContext applicationContext;
    /**
    * 实现ApplicationContextAware接口的回调方法,设置上下文环境
    */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
    SpringContextUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
    return applicationContext;
    }

    /**
    * 获取bean对象
    *
    * @param name bean名称
    * @return Object 一个以所给名字注册的bean的实例
    */
    public static Object getBean(String name) {
    return applicationContext.getBean(name);
    }
    }

    // 在其他地方可以这样子直接获取指定的bean
    BusniessServiceImpl businessServiceImpl = (BusinessServiceImpl) SpringContextUtil.get("businessServiceImpl"); // 需要注意的是,如果放在应用初始化的过程中,那么该类中的applicationContext可能还没有初始化,可以sleep以下或者其他方式

AOP切片

  • 切片的功能类似于中间件,或者说插件

applicationContext.xml中定义切片:

1
2
3
4
5
6
7
8
9
10
<bean id="myLogAspect" class="net.haofly.commons.util.LogAspect"></bean>
<aop:config>
<!-- 设置切入点 -->
<aop:pointcut expression="execution(* net.haofly.cloud.service.*.impl.*.*Impl.*(..)) and !execution(* net.haofly.service.tt.impl.ServerImpl.createServer(..))" id="myPointcut"/> <!-- 排除某个方法直接用! -->

<!-- 设置切面: 将指定bean对象中的某个方法切入到某个切入点,这里是把日志里面的validate方法切入到上面那些切入点中 -->
<aop:aspect ref="myLogAspect">
<aop:around method="validate" pointcut-ref="myPointcut"/>
</aop:aspect>
</aop:config>

TroubleShooting

  • 启动时在Initializing Spring FrameworkServlet 'spring'这一句日志时候,可能是以下原因之一
    • Mybatisxml文件的id可能重复了
扩展阅读
坚持原创技术分享,谢谢支持

欢迎关注我的其它发布渠道