2.3 SpringBoot项目代码结构最佳实践

2016-02-19 21:56:23 25,010 3

SpringBoot对于我们的项目的代码组织结构并没有特殊的要求,不过也有一些推荐的最佳实践。例如,每一个类都应在一个包下面,而不应该直接放在classes目录下,因为这可能会导致一些注解,例如@ComponentScan, @EntityScan or @SpringBootApplication失效。

对于@EnableAutoConfiguration注解,官方建议将其放在我们项目的root package下面。例如这样:

QQ截图20160219212740.png

那么com.tianshouzhi.springbootstudy就是我们的项目的root package。通常我们会在这个包下面,放置一个类,作为项目的启动类,通常命名为Application.java。在这个启动类上,我们一般会添加以下注解:

1、@EnableAutoConfiguration。之所以建议将这个类放在root package下面,是因为这个注解在某些情况下“隐含”的包含了一些“seache package”,例如当如果的项目与JPA继承了,其就会自动扫描root package的所有字包,来寻找含有@Entity注解的类。(注意@Entity并不是Spring提供的注解,其不会自动实例化有这个注解的类,只有在与JPA整合的时候,才会自动去搜索含有注解的类)

2、@ComponentScan注解。这个注解的作用类似于我们在spring的xml配置文件中的base-package的作用。在Applcation.java上添加这个注解后,会自动所有子包,寻找含有@Repository@Service@Controller@Component@RestController@Configuration注解的类,实现实例化和依赖注入等功能。对于一些依赖的第三方jar,由于这些类上并没有添加以上的这些注解,因此通过@ComponentScan无法直接获取其实例。例如我们再进行Mybatis与Spring整合的使用,使用到SqlSessionFactory,通过@ComponentScan无法获取其实例。对于这种情况, SpringBoot官方倾向于在一个添加@Configuration注解的类上,来获取需要依赖注入的Bean。不过结合目前的Spring使用情况来说,大部分公司都是XML+注解联合使用的。因此Spring也提供了另外一个注解@ImportResource,来导入xml格式的配置文件。

3、@Configration@Import(根据个人喜好)


测试:

QQ截图20160219214844.png

按照这个目录结构分别建立这几个类,内容分别如下:

Appcation.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;

@EnableAutoConfiguration
@ComponentScan
@ImportResource (value={"applicationContext.xml" })
public class Application {

     public static void main(String[] args) {
       SpringApplication. run(Application. class, args );
    }
}

PersonController.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tianshouzhi.springbootstudy.domain.Person;
import com.tianshouzhi.springbootstudy.service.PersonService;

@RestController
public class PersonController {

     @Autowired
     private PersonService personService ;
    
     public PersonController() {
       System. out .println(" 我是 PersonController,我被实例化了 " );
    }

     @RequestMapping( "/person" )
     public Person test(){
        return personService .getPerson();
    }
}

PersonService.java

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tianshouzhi.springbootstudy.dao.PersonDao;
import com.tianshouzhi.springbootstudy.domain.Person;

@Service
public class PersonService {

     @Autowired
     private PersonDao personDao ;
    
     public PersonService() {
       System. out .println(" 我是 PersonService,我被实例化了 " );
    }

     public Person getPerson() {
        return personDao .getPerson();
    }

}

PersonDao.java:注意这个类上没有任何注解

import com.tianshouzhi.springbootstudy.domain.Person;


public class PersonDao {

  public PersonDao() {
     super ();
    System. out .println(" 我是 PersonDao,我被实例化了 " );
 }

  public Person getPerson() {
     return new Person( "田守枝 " ," 合肥 ");
 }

}

Person.java

public class Person {
    
    private String username ;
    private String address ;
   
    public Person(String username , String address ) {
       super ();
       this .username = username;
       this .address = address;
   }

    public String getUsername() {
       return username ;
   }

    public void setUsername(String username ) {
       this .username = username;
   }

    public String getAddress() {
       return address ;
   }

    public void setAddress(String address ) {
       this .address = address;
   }
}

ApplicationContext.xml

<?xml version = "1.0" encoding ="UTF-8" ?>
<beans xmlns ="http://www.springframework.org/schema/beans"
     xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

     <bean id= "personDao" class ="com.tianshouzhi.springbootstudy.dao.PersonDao" ></bean>
</beans>

运行 Applcation.java,控制台输出

Image.png

可以看到 PersonDao、PersonService 、PersonController都被实例化了,其中 PersonService和PersonCtroller 是通过@ComponentScan的方式实例化的,而 PersonDao是通过在xml 文件中配置的方式进行实例化,都起作用了。

在浏览器中输入: http://localhost:8080/person

Image.png

可以看到我们的应用正常的起作用了。


补充,在这个例子中,我们在 Applcation.java中添加了两个注解

@EnableAutoConfiguration

@ComponentScan

而我们可以使用另外一个注解来代替 @SpringBootApplication,这个注解的作用相当于同时添加了

@EnableAutoConfiguration

@ComponentScan

@Configuration