SpringBootWeb AOP&SpringBoot原理篇【6】

一、SpringBootWeb AOP

在这里插入图片描述
在这里插入图片描述

1 事务管理

1.1 事务回顾

在这里插入图片描述

1.2 Spring事务管理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

    @Transactional // spring事务管理
    @Override
    public void delete(Integer id) {
        deptMapper.deleteById(id); //根据ID删除部门数据

        empMapper.deleteByDeptId(id); //根据部门的ID删除该部门下的员工数据

    }
    /**
     * 根据部门的ID删除该部门下的员工数据
     * @param deptId
     */
    @Delete("delete from emp where dept_id = #{deptId}")
    void deleteByDeptId(Integer deptId);
#spring事务管理日志
logging:
  level:
    org.springframework.jdbc.support.JdbcTransactionManager: debug

1.3 事务进阶

rollbackFor 异常回滚的属性

在这里插入图片描述
在这里插入图片描述

	//所有的异常都会进行事务的回滚操作,默认只有出现运行时异常才回滚事务
    @Transactional(rollbackFor = Exception.class) // spring事务管理
    @Override
    public void delete(Integer id) {
        deptMapper.deleteById(id); //根据ID删除部门数据

        empMapper.deleteByDeptId(id); //根据部门的ID删除该部门下的员工数据

    }
propagation 事物的传播行为
  • 数据库
create table dept_log
(
    id          int auto_increment comment '主键ID'
        primary key,
    create_time datetime     not null comment '操作时间',
    description varchar(300) null comment '操作日志的描述'
);
  • DeptLog.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * 部门操作日志类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeptLog {
    private Integer id; //操作日志ID
    private LocalDateTime createTime; //创建时间
    private String description; //操作描述
}
  • DeptLogService.java
/**
 * 部门操作日志管理
 */
public interface DeptLogService {
    void insert(DeptLog deptLog);
}
  • DeptLogServiceImpl.java
@Service
public class DeptLogServiceImpl implements DeptLogService {

    @Autowired
    private DeptLogMapper deptLogMapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void insert(DeptLog deptLog) {
        deptLogMapper.insert(deptLog);
    }
}
  • DeptLogMapper.java
/**
 * 部门操作日志管理
 */
@Mapper
public interface DeptLogMapper {

    @Insert("insert into dept_log(create_time,description)values (#{createTime}, #{description})")
    void insert(DeptLog deptLog);
}
  • DeptServiceImpl.java
    //所有的异常都会进行事务的回滚操作,默认只有出现运行时异常才回滚事务
    @Transactional(rollbackFor = Exception.class) // spring事务管理
    @Override
    public void delete(Integer id) {
        try {
            deptMapper.deleteById(id); //根据ID删除部门数据

            int i = 1/0;
            //if(true) {throw new Exception("出错了....");}

            empMapper.deleteByDeptId(id); //根据部门的ID删除该部门下的员工数据
        } finally {
            DeptLog deptLog = new DeptLog();
            deptLog.setCreateTime(LocalDateTime.now());
            deptLog.setDescription("执行了解散部门的操作,此次解散的是" + id + "号部门");
            deptLogService.insert(deptLog);
        }

    }

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 AOP基础

2.1 AOP概述

在这里插入图片描述
在这里插入图片描述

2.2 AOP快速入门 : 统计各个业务层方法执行耗时

在这里插入图片描述

        <!--AOP-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
  • TimeAspect.java
package com.itcast.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Slf4j
@Component // 标注为bean对象
@Aspect //AOP类
public class TimeAspect {

    @Around("execution(* com.itcast.service.*.*(..))") //返回值 包名.类名.方法名.. 切入点表达式
    public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
        //1.记录开始时间
        long begin = System.currentTimeMillis();

        //2.调用原始方法运行
        Object result = joinPoint.proceed();

        //3.记录结束时间,计算方法执行耗时
        long end = System.currentTimeMillis();
        log.info(joinPoint.getSignature() + "方法执行耗时:{}ms", end - begin); //哪个方法执行耗时

        return result; // 原始方法的返回值,需要返回回去
    }
}

在这里插入图片描述
在这里插入图片描述

2.3 AOP核心概念

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.4 AOP进阶

通知类型

在这里插入图片描述

@Slf4j
@Component
@Aspect
public class MyAsperct1 {

    @Before("execution(* com.itcast.service.impl.DeptServiceImpl.*(..))")
    public void before() {
        log.info("before......");
    }

    @Around("execution(* com.itcast.service.impl.DeptServiceImpl.*(..))")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("around before......");

        //调用目标对象的原始方法执行
        Object result = joinPoint.proceed();
        System.out.println(joinPoint.getSignature());

        log.info("around after......");
        return result;
    }

    @After("execution(* com.itcast.service.impl.DeptServiceImpl.*(..))")
    public void after() {
        log.info("after......");
    }

    @AfterReturning("execution(* com.itcast.service.impl.DeptServiceImpl.*(..))")
    public void afterReturning() {
        log.info("afterReturning......");
    }

    @AfterThrowing("execution(* com.itcast.service.impl.DeptServiceImpl.*(..))")
    public void afterThrowing() {
        log.info("afterThrowing......");
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

多个切面类通知顺序

在这里插入图片描述

@SpringBootTest
public class TestAop {

    @Autowired
    private DeptService deptService;

    @Test
    public void testDelete() {
        deptService.delete(10);
    }

    @Test
    public void testAopList() {
        List<Dept> list = deptService.list();
        for (Dept dept : list) {
            System.out.println(dept);
        }
    }

    @Test
    public void testAopGetById() {
        Dept dept = deptService.getById(1);
        System.out.println(dept);
    }
}
@Order(3)
@Slf4j
@Component
@Aspect
public class MyAspect2 {

    @Before("com.itcast.aop.MyAspect1.pt()")
    public void before() {
        log.info("before ... 2");
    }

    @After("com.itcast.aop.MyAsperct1.pt()")
    public void after() {
        log.info("after ... 2");
    }
}
@Order(2)
@Slf4j
@Component
@Aspect
public class MyAspect3 {

    @Before("com.itcast.aop.MyAspect1.pt()")
    public void before() {
        log.info("before ... 3");
    }

    @After("execution(* com.itcast.service.impl.DeptServiceImpl.*(..))")
    public void after() {
        log.info("after ... 3");
    }
}

在这里插入图片描述

切入点表达式–execution

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//切面类
@Slf4j
@Component
@Aspect
public class MyAspect6 {

    //execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数)throws 异常?)
    //@Pointcut("execution(public void com.itcast.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
    //@Pointcut("execution(void com.itcast.service.impl.DeptServiceImpl.delete(java.lang.Integer))")
    //@Pointcut("execution(void delete(java.lang.Integer))") //包名.类名不建议省略
    //@Pointcut("execution(void com.itcast.service.DeptService.delete(java.lang.Integer))")

    //@Pointcut("execution(void com.itcast.service.DeptService.*(java.lang.Integer))")
    //@Pointcut("execution(* com.*.service.DeptService.*(*))")
    //@Pointcut("execution(* com.*.service.*Service.delete*(*))")

    //@Pointcut("execution(* com.*.service.DeptService.*(..))")
    //@Pointcut("execution(* com..DeptService.*(..))")
    //@Pointcut("execution(* com..*.*(..))")
    //@Pointcut("execution(* *(..))") //慎用

    @Pointcut("execution(* com.itcast.service.DeptService.list()) ||" +
            "execution(* com.itcast.service.DeptService.delete(java.lang.Integer))")
    public void pt() {
    }

    @Before("pt()")
    public void before() {
        log.info("MyAspect6 ... before ....");
    }
}

在这里插入图片描述

切入点表达式–@annotation

在这里插入图片描述

  • MyLog.java
@Retention(RetentionPolicy.RUNTIME) //什么时候生效,运行时生效
@Target(ElementType.METHOD) //注解标识方法
public @interface MyLog {
}
@Slf4j
@Component
@Aspect
public class MyAspect7 {

    //匹配DeptServiceImpl中的list()和delete(Integer id)方法
    //@Pointcut("execution(* com.itcast.service.DeptService.list()) || execution(* com.itcast.service.DeptService.delete(java.lang.Integer))")
    @Pointcut("@annotation(com.itcast.aop.MyLog)")
    public void pt() {
    }

    @Before("pt()")
    public void before() {
        log.info("MyAspect7 ... before ....");
    }
}
@Service
@Slf4j
public class DeptServiceImpl implements DeptService {

    @Autowired
    private DeptMapper deptMapper;

    @MyLog
    @Override
    public List<Dept> list() {
        List<Dept> deptList = deptMapper.list();
        return deptList;
    }

    @MyLog
    @Override
    public void delete(Integer id) {
        //1. 删除部门
        deptMapper.delete(id);
    }

}

在这里插入图片描述

连接点

在这里插入图片描述
在这里插入图片描述

@Slf4j
@Component
@Aspect
public class MyAspect8 {

    @Pointcut("execution(* com.itcast.service.DeptService.*(..))")
    private void pt() {
    }

    @Before("pt()")
    public void before(JoinPoint joinPoint) {
        log.info("MyAspect8 ... before ....");
    }

    @Around("pt()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("MyAspect8 around before ...");

        //1.获取 目标对象的类名
        String className = joinPoint.getTarget().getClass().getName();
        log.info("目标对象的类名:{}", className);

        //2.获取 目标方法的方法名
        String methodName = joinPoint.getSignature().getName();
        log.info("目标方法的方法名:{}", methodName);

        //3.获取 目标方法运行时传入的参数
        Object[] args = joinPoint.getArgs();
        log.info("目标方法运行时传入的参数:{}", Arrays.toString(args));

        //4.获取 目标方法执行
        Object result = joinPoint.proceed();

        //5.获取 目标方法运行时的返回值
        log.info("目标方法运行时的返回值:{}", result);

        log.info("MyAspect8 around after ...");
        return result;
    }
}

在这里插入图片描述
在这里插入图片描述

2.5 AOP案例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

引入AOP的起步依赖
        <!--AOP-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
导入资料中准备好的数据表结构,并引入对应的实体类
-- 操作日志表
create table operate_log(
    id int unsigned primary key auto_increment comment 'ID',
    operate_user int unsigned comment '操作人ID',
    operate_time datetime comment '操作时间',
    class_name varchar(100) comment '操作的类名',
    method_name varchar(100) comment '操作的方法名',
    method_params varchar(1000) comment '方法参数',
    return_value varchar(2000) comment '返回值',
    cost_time bigint comment '方法执行耗时, 单位:ms'
) comment '操作日志表';
  • OperateLog.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OperateLog {
    private Integer id; //ID
    private Integer operateUser; //操作人ID
    private LocalDateTime operateTime; //操作时间
    private String className; //操作类名
    private String methodName; //操作方法名
    private String methodParams; //操作方法参数
    private String returnValue; //操作方法返回值
    private Long costTime; //操作耗时
}
  • OperateLogMapper.java
@Mapper
public interface OperateLogMapper {

    //插入日志数据
    @Insert("insert into operate_log (operate_user, operate_time, class_name, method_name, method_params, return_value, cost_time) " +
            "values (#{operateUser}, #{operateTime}, #{className}, #{methodName}, #{methodParams}, #{returnValue}, #{costTime});")
    public void insert(OperateLog log);

}
自定义注解@Log
  • LogAspect.java
//元注解
@Retention(RetentionPolicy.RUNTIME) //运行时生效
@Target(ElementType.METHOD) //目标对象:方法上
public @interface Log {
}
定义切面类,完成记录操作日志的逻辑
  • LogAspect.java
@Slf4j
@Component
@Aspect //切面类
public class LogAspect {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private OperateLogMapper operateLogMapper;

    @Around("@annotation(com.itcast.anno.Log)")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {

        //操作人ID - 当前登录员工ID  从令牌中获取ID
        //获取请求头中的JWT令牌,解析令牌
        String jwt = request.getHeader("token");
        Claims claims = JwtUtils.parseJWT(jwt);
        Integer operateUser = (Integer) claims.get("id");

        //操作时间
        LocalDateTime operateTime = LocalDateTime.now();

        //操作类名
        String className = joinPoint.getTarget().getClass().getName();

        //操作方法名
        String methodName = joinPoint.getSignature().getName();

        //操作方法参数
        Object[] args = joinPoint.getArgs();
        String methodParams = Arrays.toString(args);

        long start = System.currentTimeMillis();
        //调用原始目标方法运行
        Object result = joinPoint.proceed();
        long end = System.currentTimeMillis();

        //方法返回值
        String returnValue = JSONObject.toJSONString(result);

        //操作耗时
        long costTime = end - start;

        //日志信息包含:操作人、操作时间、执行方法的全类名、执行方法名、方法运行时参数、返回值、方法执行时长
        //记录操作日志
        OperateLog operateLog = new OperateLog(null, operateUser, operateTime, className, methodName, methodParams, returnValue, costTime);
        operateLogMapper.insert(operateLog);

        log.info("AOP记录操作日志:{}", operateLog);

        return result;
    }
}
/**
 * 员工管理Controller
 */
@Slf4j
@RestController
@RequestMapping("/emps")
@Api(tags = "员工管理")
public class EmpController {

    @Autowired
    private EmpService empService;

    /**
     * 分页查询
     *
     * @param page
     * @param pageSize
     * @return
     */
    @GetMapping
    public Result page(@RequestParam(defaultValue = "1") Integer page,
                       @RequestParam(defaultValue = "10") Integer pageSize,
                       String name, Short gender,
                       @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin,
                       @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
        log.info("分页查询,参数:{},{},{},{},{},{}", page, pageSize, name, gender, begin, end);

        //调用service分页查询
        PageBean pageBean = empService.page(page, pageSize, name, gender, begin, end);

        return Result.success(pageBean);
    }

    @Log
    @DeleteMapping("/{ids}")
    public Result delete(@PathVariable List<Integer> ids) { //PathVariable:路径参数

        log.info("批量删除员工,参数ids:{}", ids);

        //调用service删除员工
        empService.delete(ids);

        return Result.success();
    }

    @Log
    @PostMapping
    public Result save(@RequestBody Emp emp) {

        log.info("新增员工,emp:{}", emp);
        empService.save(emp);

        return Result.success();
    }

    @GetMapping("/{id}")
    public Result getById(@PathVariable Integer id) {

        log.info("根据id查询员工信息:{}", id);
        Emp emp = empService.getById(id);

        return Result.success(emp);
    }

    @Log
    @PutMapping
    public Result update(@RequestBody Emp emp) {

        log.info("更新员工信息:{}", emp);
        empService.update(emp);

        return Result.success();
    }

}
/**
 * 部门管理Controller
 */
@Slf4j
@RestController
@RequestMapping("/depts")
@Api(tags = "部门管理")
public class DeptController {

    //获取日志记录对象
    //private static Logger logger = LoggerFactory.getLogger(DeptController.class);

    @Autowired //注入
    private DeptService deptService;

    /**
     * 部门列表数据查询
     *
     * @return 返回所有部门数据
     */
    //@RequestMapping(value = "/depts",method = RequestMethod.GET)  //指定请求方式为get
    @GetMapping
    @ApiOperation(value = "查询全部部门")
    public Result list() {
        //logger.info("查询部门全部数据");
        log.info("查询部门全部数据");

        //调用service查询部门数据
        List<Dept> deptList = deptService.list();

        return Result.success(deptList);
    }

    /**
     * 删除部门
     *
     * @return
     */
    @Log
    @ApiOperation(value = "根据id删除部门")
    @DeleteMapping("/{id}")
    public Result delete(@ApiParam(value = "部门id", required = true) @PathVariable Integer id) {
        log.info("根据id删除部门:{}", id);

        //调用service根据id删除部门
        deptService.delete(id);

        return Result.success();
    }

    /**
     * 新增部门
     *
     * @param dept 部门接收JSON数据
     * @return
     */
    @Log
    @PostMapping
    @ApiOperation(value = "新增部门")
    public Result add(@ApiParam(value = "部门", required = true) @RequestBody Dept dept) {

        log.info("新增部门:{}", dept);

        //调用service新增部门
        deptService.add(dept);

        return Result.success();
    }

    /**
     * 根据id查询部门数据
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    @ApiOperation(value = "根据id查询部门数据")
    public Result getDeptById(@ApiParam(value = "部门id", required = true) @PathVariable Integer id) {

        log.info("根据id查询部门数据:{}", id);

        //调用service根据id查询部门
        Dept dept = deptService.getDeptById(id);

        return Result.success(dept);
    }

    /**
     * 修改部门
     *
     * @param dept
     * @return
     */
    @Log
    @PutMapping
    @ApiOperation(value = "修改部门")
    public Result update(@ApiParam(value = "部门", required = true) @RequestBody Dept dept) {

        log.info("根据id修改部门:{}", dept);

        //调用service的更新部门
        deptService.updateDeptById(dept);

        return Result.success();
    }

}

在这里插入图片描述

在这里插入图片描述

二、SpringBoot原理篇

1 配置优先级

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2 Bean管理

环境准备

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!--mybatis起步依赖-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <!--mysql驱动-->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--PageHelper分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.2</version>
        </dependency>

        <!--阿里云OSS-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.15.1</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!-- no more than 2.3.3-->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--JWT令牌-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

        <!--fastJSON-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.76</version>
        </dependency>
  • application.yml
spring:
  #数据库连接信息
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/tlias
    username: root
    password: 1234
#Mybatis配置
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true
  • Dept.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
    private Integer id;
    private String name;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}
  • Result.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    private Integer code;//响应码,1 代表成功; 0 代表失败
    private String msg;  //响应码 描述字符串
    private Object data; //返回的数据

    //增删改 成功响应
    public static Result success(){
        return new Result(1,"success",null);
    }
    //查询 成功响应
    public static Result success(Object data){
        return new Result(1,"success",data);
    }
    //失败响应
    public static Result error(String msg){
        return new Result(0,msg,null);
    }
}
  • DeptMapper.java
@Mapper
public interface DeptMapper {
    //查询全部部门数据
    @Select("select * from dept")
    List<Dept> list();

    //删除部门
    @Delete("delete from dept where id = #{id}")
    void delete(Integer id);

    //新增部门
    @Insert("insert into dept(name, create_time, update_time) values (#{name},#{createTime},#{updateTime})")
    void save(Dept dept);
}
  • DeptService.java
public interface DeptService {
    /**
     * 查询所有的部门数据
     * @return
     */
    List<Dept> list();

    /**
     * 删除部门
     * @param id
     */
    void delete(Integer id);

    /**
     * 新增部门
     * @param dept
     */
    void save(Dept dept);
}
  • DeptServiceImpl.java
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;

    @Override
    public List<Dept> list() {
        List<Dept> deptList = deptMapper.list();
        return deptList;
    }

    @Override
    public void delete(Integer id) {
        deptMapper.delete(id);
    }

    @Override
    public void save(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        deptMapper.save(dept);
    }
}
  • DeptController.java
@RestController
@RequestMapping("/depts")
public class DeptController {

    @Autowired
    private DeptService deptService;

    @GetMapping
    public Result list(){
        List<Dept> deptList = deptService.list();
        return Result.success(deptList);
    }

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id)  {
        deptService.delete(id);
        return Result.success();
    }

    @PostMapping
    public Result save(@RequestBody Dept dept){
        deptService.save(dept);
        return Result.success();
    }
}

获取Bean

在这里插入图片描述

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; // IOC容器

    @Test
    public void testGetBean() {
        //根据bean的名称获取
        DeptController bean1 = (DeptController) applicationContext.getBean("deptController");
        System.out.println("bean1 = " + bean1);

        //根据bean的类型获取
        DeptController bean2 = applicationContext.getBean(DeptController.class);
        System.out.println("bean2 = " + bean2);

        //根局bean的名称 及 类型获取
        DeptController bean3 = applicationContext.getBean("deptController", DeptController.class);
        System.out.println("bean3 = " + bean3);

    }
}

在这里插入图片描述

bean的作用域

在这里插入图片描述
在这里插入图片描述

//@Lazy //延迟初始化,第一次使用时实例化,后面就不会在实例化
@Scope("prototype") // 非单例
@RestController
@RequestMapping("/depts")
public class DeptController {

    @Autowired
    private DeptService deptService;

    public DeptController() {
        System.out.println("DeptController constructor ... ");
    }
}
    //bean的作用域
    @Test
    public void testScope() {
        for (int i = 0; i < 10; i++) {
            DeptController bean = applicationContext.getBean(DeptController.class);
            System.out.println("bean" + i + " = " + bean);
        }
    }

在这里插入图片描述

第三方bean

在这里插入图片描述

  • 1.xml
<?xml version="1.0" encoding="UTF-8" ?>
<emp>
    <name>Tom</name>
    <age>18</age>
</emp>
        <!--Dom4j-->
        <dependency>
            <groupId>org.dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>2.1.3</version>
        </dependency>
@SpringBootApplication
public class SpringbootWebConfig2Application {

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

    //声明第三方bean
    @Bean //将当前方法的返回值对象交给IOC容器管理,成为IOC容器bean
    public SAXReader saxReader() {
        return new SAXReader();
    }

}
    //第三方的bean管理
    @Test
    public void testThirdBean() throws DocumentException {
        SAXReader saxReader = new SAXReader();

        //读取xml文件,对里面的内容进行解析
        Document document = saxReader.read(this.getClass().getClassLoader().getResource("1.xml"));
        Element rootElement = document.getRootElement();
        String name = rootElement.element("name").getText();
        String age = rootElement.element("age").getText();

        System.out.println(name + " : " + age);
    }

在这里插入图片描述
在这里插入图片描述

    @Autowired
    private SAXReader saxReader;

    //第三方的bean管理
    @Test
    public void testThirdBean() throws DocumentException {
        //SAXReader saxReader = new SAXReader();

        //读取xml文件,对里面的内容进行解析
        Document document = saxReader.read(this.getClass().getClassLoader().getResource("1.xml"));
        Element rootElement = document.getRootElement();
        String name = rootElement.element("name").getText();
        String age = rootElement.element("age").getText();

        System.out.println(name + " : " + age);
    }
  • CommonConfig.java
package com.itcast.config;

import org.dom4j.io.SAXReader;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration //配置类
public class CommonConfig {

    //声明第三方bean
    @Bean //将当前方法的返回值对象交给IOC容器管理,成为IOC容器bean
    public SAXReader saxReader() {
        return new SAXReader();
    }
}

在这里插入图片描述

    @Test
    public void testGetBean2(){
        Object saxReader = applicationContext.getBean("saxReader");
        System.out.println("saxReader = " + saxReader);
    }
@Configuration //配置类
public class CommonConfig {

    //声明第三方bean
    @Bean //将当前方法的返回值对象交给IOC容器管理,成为IOC容器bean
    //通过@Bean注解的name/value属性指定bean名称,如果未指定,默认是方法名
    public SAXReader saxReader(DeptService deptService) {
        System.out.println(deptService.getClass());
        return new SAXReader();
    }
}

在这里插入图片描述
在这里插入图片描述

3 SpringBoot原理篇

在这里插入图片描述
在这里插入图片描述

起步依赖

在这里插入图片描述
在这里插入图片描述

自动配置

/**
 * 自动配置原理测试
 */
@SpringBootTest
public class AutoConfigurationTests {

    @Autowired
    private Gson gson;

    @Test
    public void testJson(){
        String json = gson.toJson(Result.success());
        System.out.println(json);
    }
}

在这里插入图片描述

自动配置原理

在这里插入图片描述
准备springboot-utils环境:

  • TokenParser.java
@Component
public class TokenParser {

    public void parse(){
        System.out.println("TokenParser ... parse ...");
    }

}
  • HeaderGenerator.java
public class HeaderGenerator {

    public void generate(){
        System.out.println("HeaderGenerator ... generate ...");
    }

}
  • HeaderParser.java
public class HeaderParser {

    public void parse(){
        System.out.println("HeaderParser ... parse ...");
    }

}
  • HeaderConfig.java
@Configuration
public class HeaderConfig {

    @Bean
    public HeaderParser headerParser(){
        return new HeaderParser();
    }

    @Bean
    public HeaderGenerator headerGenerator(){
        return new HeaderGenerator();
    }
}
  • MyImportSelector.java
public class MyImportSelector implements ImportSelector {
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.example.HeaderConfig"};
    }
}
  • EnableHeaderConfig.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)
public @interface EnableHeaderConfig {
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//@ComponentScan({"com.example","com.itcast"})

//@Import({TokenParser.class}) // 导入普通类,交给IOC容器
//@Import({HeaderConfig.class}) // 导入配置类,交给IOC容器
//@Import({MyImportSelector.class}) // 导入ImportSelector接口实现类

@EnableHeaderConfig
@SpringBootApplication
public class SpringbootWebConfig2Application {

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

    //声明第三方bean
//    @Bean //将当前方法的返回值对象交给IOC容器管理,成为IOC容器bean
//    public SAXReader saxReader() {
//        return new SAXReader();
//    }

}
/**
 * 自动配置原理测试
 */
@SpringBootTest
public class AutoConfigurationTests {

    @Autowired
    private Gson gson;

    @Autowired
    private ApplicationContext applicationContext;

    @Test
    public void testJson() {
        String json = gson.toJson(Result.success());
        System.out.println(json);
    }

    //获取TokenParser
    @Test
    public void testTokeParser() {
        System.out.println(applicationContext.getBean(TokenParser.class));
    }

    //获取HeadParser
    @Test
    public void testHeaderParser() {
        System.out.println(applicationContext.getBean(HeaderParser.class));
    }

    //获取HeaderGenerator
    @Test
    public void testHeadGenerator() {
        System.out.println(applicationContext.getBean(HeaderGenerator.class));
    }

}
自动配置原理–源码跟踪

在这里插入图片描述
在这里插入图片描述

自动配置原理–@Conditional

在这里插入图片描述
在这里插入图片描述

@Configuration
public class HeaderConfig {

    @Bean
    //@ConditionalOnClass(name = "io.jsonwebtoken.Jwts") // 环境中存在指定的这个类,才会将bean加入到IOC容器中
    //@ConditionalOnMissingBean // 不存在该类型的bean,才会将该bean加入IOC容器中 -- 制定类型(value属性) 或 名称(name属性)
    @ConditionalOnProperty(name = "name", havingValue = "itcast") // 配置文件中存在指定的属性与值,才会将该bean加入IOC容器中
    public HeaderParser headerParser() {
        return new HeaderParser();
    }

    @Bean
    public HeaderGenerator headerGenerator() {
        return new HeaderGenerator();
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

springboot 案例(自定义starter)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

aliyun-oss-spring-boot-autoconfigure

在这里插入图片描述

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--阿里云OSS-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.15.1</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!--no more than 2.3.3-->
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.3.3</version>
        </dependency>
    </dependencies>

</project>

  • AliOSSProperties.java
@ConfigurationProperties(prefix = "aliyun.oss")//读取oss节点
public class AliOSSProperties {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    public String getAccessKeyId() {
        return accessKeyId;
    }

    public void setAccessKeyId(String accessKeyId) {
        this.accessKeyId = accessKeyId;
    }

    public String getAccessKeySecret() {
        return accessKeySecret;
    }

    public void setAccessKeySecret(String accessKeySecret) {
        this.accessKeySecret = accessKeySecret;
    }

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }
}
  • AliOSSUtils.java
/**
 * 阿里云OSS工具类
 */
public class AliOSSUtils {

    private AliOSSProperties aliOSSProperties;

    public AliOSSProperties getAliOSSProperties() {
        return aliOSSProperties;
    }

    public void setAliOSSProperties(AliOSSProperties aliOSSProperties) {
        this.aliOSSProperties = aliOSSProperties;
    }

    /**
     * 实现上传图片到OSS
     */
    public String upload(MultipartFile file) throws IOException {

        //获取阿里云OSS参数
        String endpoint = aliOSSProperties.getEndpoint();
        String accessKeyId = aliOSSProperties.getAccessKeyId();
        String accessKeySecret = aliOSSProperties.getAccessKeySecret();
        String bucketName = aliOSSProperties.getBucketName();

        // 获取上传的文件的输入流
        InputStream inputStream = file.getInputStream();

        // 避免文件覆盖
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

        //fileName上传到OSS指定文件目录
        fileName = "tlias" + "/" + fileName;

        //上传文件到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, inputStream);

        //文件访问路径
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;

        // 关闭ossClient
        ossClient.shutdown();

        return url;// 把上传到oss的路径返回
    }

}
  • AliOSSAutoConfiguration.java
@Configuration
@EnableConfigurationProperties(AliOSSProperties.class) // 直接导入到IOC容器中,成为IOC容器中的bean
public class AliOSSAutoConfiguration {

    @Bean
    public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties) {
        AliOSSUtils aliOSSUtils = new AliOSSUtils();
        aliOSSUtils.setAliOSSProperties(aliOSSProperties);
        return aliOSSUtils;
    }

}
  • src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
 com.aliyun.oss.AliOSSAutoConfiguration
spring-oss-spring-boot-starter

在这里插入图片描述

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>spring-oss-spring-boot-starter</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

springboot-autoconfiguration-test

在这里插入图片描述

  • pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itcast</groupId>
    <artifactId>springboot-autoconfiguration-test</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>11</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>spring-oss-spring-boot-starter</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

  • application.properties
##阿里云OSS配置
aliyun.oss.endpoint=https://oss-cn-hangzhou.aliyuncs.com
aliyun.oss.accessKeyId=xxxxxxxxxx
aliyun.oss.accessKeySecret=xxxxxxxxxxxxxxxxxxxxx
aliyun.oss.bucketName=web-tlias-20231216
  • UploadController.java
@RestController
public class UploadController {

    @Autowired
    private AliOSSUtils aliOSSUtils;

    @PostMapping("/upload")
    public String upload(MultipartFile image) throws Exception {
        //上传文件到阿里云 OSS
        String url = aliOSSUtils.upload(image);

        return url;
    }

}

在这里插入图片描述

4 总结

在这里插入图片描述
在这里插入图片描述

  • 21
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良辰美景好时光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值