Web入门-分层解耦

1 三层架构:

单一职责原则->

  • controller:控制层,接收前端发送的请求,对请求进行处理,并相应数据。
  • service:业务逻辑层,处理具体的业务逻辑。
  • dao:数据访问层(Data Access Object)(持久层),负责数据访问操作,增删改查

目的:复用性强、便于维护、利于拓展

面向接口的思想。

示例:以上篇EmpController.java为例,将其拆封到三层架构:

1.1.DAO:

创建接口:EmpDao.java:

public interface EmpDao {
    //获取员工列表数据
    public List<Emp> listEmp();
}

实现接口的一种类:EmpDaoA.java:

public class EmpDaoA implements EmpDao {
   @Override
    public List<Emp> listEmp() {
        //1.加载解析xml
        String file =this.getClass().getClassLoader().getResource("static/emp.xml").getFile();//此处参数为"emp.xml"就不正常运行(有时候)
        System.out.println(file);
        List<Emp> empList= XmlParserUtils.parse(file, Emp.class);
        return empList;
    }
}

1.2 Service:

创建接口:EmpService.java

public interface EmpService {
    public List<Emp> listEmp();
}

实现类:EmpServiceA.java


public class EmpServiceA implements EmpService{

    private EmpDao empDao=new EmpDaoA();

    @Override
    public List<Emp> listEmp() {
        //1.调用DAO获取数据对象
        List<Emp>empList= empDao.listEmp();

        //2.对数据进行转换
        empList.stream().forEach(emp -> {
            String gender= emp.getGender();
            if("1".equals(gender))
                emp.setGender("男");
            else
                emp.setGender("女");
        });

        empList.stream().forEach(emp->{
            String job= emp.getJob();
            if("1".equals(job))
                emp.setJob("讲师");
            else if("2".equals(job))
                emp.setJob("班主任");
            else
                emp.setJob("就业指导");
        });
        return empList;
    }
}

1.3 Controller:

@RestController
public class EmpController {
    private EmpService  empService= new  EmpServiceA();

    @RequestMapping("/listEmp")
    public Result list(){
        //controller调用service获取数据
        List<Emp> empList=empService.listEmp();

        //响应
        return Result.success(empList);
    }
}

2 分层解耦:

  • 内聚:软件中各个功能模块内部的功能联系。
  • 耦合:衡量软件中各个层/模块之间的依赖、关联的程度。
  • 应该做到 高内聚低耦合,最好解除耦合

在上例中:controller层 通过private EmpService empService= new EmpServiceA(); 与service层耦合。 service层通过 “ private EmpDao empDao=new EmpDaoA();”而与DAO层耦合。

为了解耦,引入容器:将对象的创建、配置和生命周期管理从应用代码中分离出来,实现应用程序不同组件之间的解耦。

Spring的核心:

  • 控制反转:IOC。对象的创建控制权由程序自身转移到外部(容器)。
  • 依赖注入:DI。容器为应用程序提供运行时,所依赖的资源。
  • Bean对象:IOC容器中创建、管理的对象。

3 IOC&DI入门:

将上例解耦:

1.IOC: 将 service层、Dao层接口的实现类,交由IOC容器管理:@Component 对应实现类

2.DI: 为controller及service注入运行时依赖的对象:@Autowired 对应成员变量

如果要用一个接口的其他实现,就在要用的实现上注解,不用的注释掉。

如果同时有多个,需要使用@Primary 或 @Qualifier 选定,否则不能启动服务。

@RestController
public class EmpController {
    @Autowired//运行时,IOC容器将会提供该类型的bean对象,赋值于该变量
    private EmpService  empService= new  EmpServiceA();

    @RequestMapping("/listEmp")
    public Result list(){
        //controller调用service获取数据
        List<Emp> empList=empService.listEmp();

        //响应
        return Result.success(empList);
    }
}

@Component//将当前类交由IOC容器管理,成为容器中的bean
public class EmpServiceA implements EmpService{

    @Autowired//运行时,IOC容器将会提供该类型的bean对象,赋值于该变量
    private EmpDao empDao;

    @Override
    public List<Emp> listEmp() {
        //1.调用DAO获取数据对象
        List<Emp>empList= empDao.listEmp();

        //2.对数据进行转换
        empList.stream().forEach(emp -> {
            String gender= emp.getGender();
            if("1".equals(gender))
                emp.setGender("男");
            else
                emp.setGender("女");
        });

        empList.stream().forEach(emp->{
            String job= emp.getJob();
            if("1".equals(job))
                emp.setJob("讲师");
            else if("2".equals(job))
                emp.setJob("班主任");
            else
                emp.setJob("就业指导");
        });
        return empList;
    }
}

@Component//将当前类交由IOC容器管理,成为容器中的bean
public class EmpDaoA implements EmpDao {
    @Override//运行时,IOC容器将会提供该类型的bean对象,赋值于该变量
    public List<Emp> listEmp() {
        //1.加载解析xml
        String file =this.getClass().getClassLoader().getResource("static/emp.xml").getFile();//此处参数为"emp.xml"就不正常运行
        //System.out.println(file);
        List<Emp> empList= XmlParserUtils.parse(file, Emp.class);
        return empList;
    }
}

3.1 IOC:

Bean的声明:

要把某个对象交给IOC容器管理,需要在对应的类上加一下注释:

注解说明位置
@Component声明bean的基础注解不属于以下三类时,用此注解
@Controller@Component的衍生注解标注在控制器类上
@Service@Component的衍生注解标注在业务类上
@Repository@Component的衍生注解标注在数据访问类上(由于与mybatis整合,用的少)
  • 声明bean的时候,可以通过value属性指定bean的名字,如果没有指定,默认为类名首字母小写。
  • 使用以上四个注解都可以声明Bean,但在springboot中,声明控制器controllerbean只能用@Controller

Bean组件扫描:

  • 申明的bean注解,想要生效,还需要被组件扫描注解@ComponentScan扫描,
  • @ComponentScan注解没有显示配置,实际上包含在了启动类声明注解@SpringBootApplication中,默认扫描范围为启动类所在包及其子包

3.2 DI 依赖注入:

  1. 依赖注入的注解
    • @Autowired:默认按照类型自动装配。
    • 如果同类型的bean存在多个:
      • @Primary
      • @Autowired + @Qualifier(“bean的名称”)
      • @Resource(name=”bean的名称”)
  2. @Resource 与 @Autowired 区别
    • @Autowired 是Spring框架提供的注解,而@Resource 是JDK提供的注解。
    • @Autowired 默认是按照类型注入,而@Resource 默认是按照名称注入。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇