2023.12.7日收获

今日力扣刷题

最小覆盖子串最终实现的方案还是滑动窗口,比较特殊的是,并非所有位置都进行尝试,先固定后面的指针,当前的指针滑动到满足条件后再滑动后面的直到不满足条件,再滑动前面的,直到满足条件。

单词搜索就是一个非常简单的多起点DFS问题。唯一需要注意的是要记得记录状态的数组一定要恢复回之前的状态。

76最小覆盖子串

class Solution {
    Map<Character, Integer> ori = new HashMap<Character, Integer>();
    Map<Character, Integer> cnt = new HashMap<Character, Integer>();

    public String minWindow(String s, String t) {
        int tLen = t.length();
        for (int i = 0; i < tLen; i++) {
            char c = t.charAt(i);
            ori.put(c, ori.getOrDefault(c, 0) + 1);
        }
        int l = 0, r = -1;
        int len = Integer.MAX_VALUE, ansL = -1, ansR = -1;
        int sLen = s.length();
        while (r < sLen) {
            ++r;
            if (r < sLen && ori.containsKey(s.charAt(r))) {
                cnt.put(s.charAt(r), cnt.getOrDefault(s.charAt(r), 0) + 1);
            }
            while (check() && l <= r) {
                if (r - l + 1 < len) {
                    len = r - l + 1;
                    ansL = l;
                    ansR = l + len;
                }
                if (ori.containsKey(s.charAt(l))) {
                    cnt.put(s.charAt(l), cnt.getOrDefault(s.charAt(l), 0) - 1);
                }
                ++l;
            }
        }
        return ansL == -1 ? "" : s.substring(ansL, ansR);
    }

    public boolean check() {
        Iterator iter = ori.entrySet().iterator(); 
        while (iter.hasNext()) { 
            Map.Entry entry = (Map.Entry) iter.next(); 
            Character key = (Character) entry.getKey(); 
            Integer val = (Integer) entry.getValue(); 
            if (cnt.getOrDefault(key, 0) < val) {
                return false;
            }
        } 
        return true;
    }
}

在这里插入图片描述

class Solution {
    public boolean exist(char[][] board, String word) {
//深搜
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[0].length; j++) {
                boolean[][] bool = new boolean[board.length][board[0].length];
                if(board[i][j] == word.charAt(0)){
                    bool[i][j] = true;
                    boolean dfs = dfs(board, word, bool, i, j, 1);
                    if(dfs){
                        return true;
                    }
                }

            }
        }
        return false;
    }
       private boolean dfs(char[][] board, String word, boolean[][] bool, int i, int j,int len) {
        if(len == word.length()){
            return true;
        }
        if(i-1 >=0 && !bool[i-1][j]&&board[i-1][j]==word.charAt(len)){
            bool[i-1][j] = true;
            if(dfs(board, word, bool, i-1, j, len+1)){
                return true;
            }
            bool[i-1][j] = false;
        }
        if(i+1 < board.length && !bool[i+1][j]&&board[i+1][j]==word.charAt(len)){
            bool[i+1][j] = true;
            if(dfs(board, word, bool, i+1, j, len+1)){
                return true;
            }
            bool[i+1][j] = false;
        }
        if(j-1 >=0 && !bool[i][j-1]&&board[i][j-1]==word.charAt(len)){
            bool[i][j-1] = true;
            if(dfs(board, word, bool, i, j-1, len+1)){
                return true;
            }
            bool[i][j-1] = false;
        }
        if(j+1 < board[0].length && !bool[i][j+1]&&board[i][j+1]==word.charAt(len)){
            bool[i][j+1] = true;
            if(dfs(board, word, bool, i, j+1, len+1)){
                return true;
            }
            bool[i][j+1] = false;
        }
        return false;
    }
}

今日SpringIOC复习

Spring实现IOC/DI的方式共有三种,基于XML,基于注解方式管理Bean,基于配置类方式管理bean。
第三种是完全面向注解开发,使用的IOC容器为:

4.3.1 Bean 注解标记和扫描(loC)

需要注意的是如果不使用配置类进行扫描,那么仍然需要xml文件进行扫描
内部可以用value指定bean名字
在这里插入图片描述

4.3.2组件 (Bean) 作用域和周期方法注解

周期方法可以使用:@PostConstruct 制定初始化方法。@PreDestroy指定销毁方法

作用域:作用域注解需要放在Bean上
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON) //单例,默认值
@Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE) //多例 二选一

4.3.3 Bean 属性赋值: 引用类型自动装配 (DI)

两个注解:@Autowired和@Resource二选一,@Resource是java的规范,然后spring实现的注解其等于@Autowired+@Qualifier(value=‘test’) value用于多个bean对象时,具体哪个进行导入。

4.3.4 Bean 属性赋值: 基本类型属性赋值 (DI)

@Value 通常用于注入外部化属性,一般用于配置文件的值的DI
如: @Value(“${catalog:hahaha}”) 其也可以用在参数的位置

4.3.5 基于注解 +XML 方式整合三层架构组件

使用这种方式创建IOC容器时,需要创建ClassPathXmlApplicationContext容器,并指定xml文件

4.4.1 完全注解开发理解

下面的三个注解都加到配置类上,在springboot中应该是加到了启动类上
@Configuration指定一个类为配置类,可以添加配置注解,替代配置xml文件

@ComponentScan(basePackages = {“包”,“包”}) 替代<context:component-scan标签实现注解扫描

@PropertySource(“classpath:配置文件地址”) 替代 <context:property-placeholder标签

4.4.2 实验一:配置类和扫描注解

@Configuration内可以使用@Bean注解声明bean对象,这种方式一般用于引入第三方框架的bean对象。
下面两个注解用于指定初始化与销毁执行的方法,具体方法还是实现在具体的bean对象的类中
@Bean(initMethod = “init”)
@Bean(destroyMethod = “cleanup”)
作用域:与@bean注解配合使用@Scope(“prototype”)

4.4.3 @Bean 定义组件与 @Bean 注解细节

先用@value引入配置文件中的值,在使用@bean和@Configuration转化为组件bean对象

bean对象之间可以通过参数的方式进行DI注入


@Bean
    public HappyMachine happyMachine(){
        return new HappyMachine();
    }
@Bean
    public HappyComponent happyComponent(HappyMachine happyMachine){
        HappyComponent happyComponent = new HappyComponent();
        //赋值
        happyComponent.setHappyMachine(happyMachine);
        return happyComponent;
    }
4.4.4 实验四: 高级特性: @lmport 扩展

就是在声明IOC容器时需要指定配置类,这太多了,可以在某个配置类上通过@lmport 来导入其他配置类,成为一个总的配置类,这样最后在创建IOC容器时只需要导入一个配置类就可以了。

4.4.5 实验五: 基于注解 + 配置类方式整合三层架构组件

AnnotationConfigApplicationContext

ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);

4.5三种配置方式总结

XML方式配置总结

  1. 所有内容写到xml格式配置文件中
  2. 声明bean通过<bean标签
  3. <bean标签包含基本信息(id,class)和属性信息 <property name value / ref
  4. 引入外部的properties文件可以通过<context:property-placeholder
  5. IoC具体容器实现选择ClassPathXmlApplicationContext对象
    XML+注解方式配置总结
  6. 注解负责标记IoC的类和进行属性装配
  7. xml文件依然需要,需要通过<context:component-scan标签指定注解范围
  8. 标记IoC注解:@Component,@Service,@Controller,@Repository
  9. 标记DI注解:@Autowired @Qualifier @Resource @Value
  10. IoC具体容器实现选择ClassPathXmlApplicationContext对象
    完全注解方式配置总结
  11. 完全注解方式指的是去掉xml文件,使用配置类 + 注解实现
  12. xml文件替换成使用@Configuration注解标记的类
  13. 标记IoC注解:@Component,@Service,@Controller,@Repository
  14. 标记DI注解:@Autowired @Qualifier @Resource @Value
  15. <context:component-scan标签指定注解范围使用@ComponentScan(basePackages = {“com.atguigu.components”})替代
  16. <context:property-placeholder引入外部配置文件使用@PropertySource({“classpath:application.properties”,“classpath:jdbc.properties”})替代
  17. <bean 标签使用@Bean注解和方法实现
  18. IoC具体容器实现选择AnnotationConfigApplicationContext对象
4.6 整合 Spring5-Test5 搭建测试环境

导入

<!--junit5测试-->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.3.1</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>6.0.6</version>
    <scope>test</scope>
</dependency>

@SpringJUnitConfig(value = {BeanConfig.class})

Spring AOP复习

5.1 场景设定和问题复现
  1. AOP一种区别于OOP的编程思维,用来完善和解决OOP的非核心代码冗余和不方便统一维护问题!
  2. 代理技术(动态代理|静态代理)是实现AOP思维编程的具体技术,但是自己使用动态代理实现代码比较繁琐!
  3. Spring AOP框架,基于AOP编程思维,封装动态代理技术,简化动态代理技术实现的框架!SpringAOP内部帮助我们实现动态代理,我们只需写少量的配置,指定生效范围即可,即可完成面向切面思维编程的实现!
5.2 解决技术代理模式

被代理是核心代码,其套通了代理的非核心逻辑代码
静态代理:需要对每个类每个方法进行代码撰写(繁琐!!!)

动态代理:
jdk要求有接口
cjlib不要求有接口

aop实际就是对动态代理的简化!!!
场景:
1.日志记录
2.事务处理
3.性能监控
4.异常处理

5.3 面向切面编程思维 (AOP)

核心名词:
1.横切关注点:与核心关注点相对,指的是与核心代码无关的关注点
2.增强:每一个关注点都要写一个方法,增强有五种1.前置2返回3异常4后置finally5环绕
3连接点:能切的方法
4切入点:真正切的点(被选的连接点)
5切面:连接点加切入点(切入点+增强)
6织入:增强这个动作
7代理:被切入的类
8目标:要被切入的类

5.5 Spring AOP 基于注解方式实现和细节

实现的底层技术:如果代理类有接口则通过JDK方式实现,且只能通过接口获取bean,因为放入IOC容器中的是代理类。如果没有接口,则通过cjlib方式实现,可以通过类来获取bean

具体的实现注解:@Aspect@Conponent@其他放在方法上的注解

// @Aspect表示这个类是一个切面类
@Aspect
// @Component注解保证这个切面类能够放入IOC容器
@Component
public class LogAspect {
        
    // @Before注解:声明当前方法是前置通知方法
    // value属性:指定切入点表达式,由切入点表达式控制当前通知方法要作用在哪一个目标方法上
    @Before(value = "execution(public int com.atguigu.proxy.CalculatorPureImpl.add(int,int))")
    public void printLogBeforeCore() {
        System.out.println("[AOP前置通知] 方法开始了");
    }
    
    @AfterReturning(value = "execution(public int com.atguigu.proxy.CalculatorPureImpl.add(int,int))")
    public void printLogAfterSuccess() {
        System.out.println("[AOP返回通知] 方法成功返回了");
    }
    
    @AfterThrowing(value = "execution(public int com.atguigu.proxy.CalculatorPureImpl.add(int,int))")
    public void printLogAfterException() {
        System.out.println("[AOP异常通知] 方法抛异常了");
    }
    
    @After(value = "execution(public int com.atguigu.proxy.CalculatorPureImpl.add(int,int))")
    public void printLogFinallyEnd() {
        System.out.println("[AOP后置通知] 方法最终结束了");
    }
    
}

JoinPoint 作为上面四种的参数,可以通过反射的方式获取方法签名、传入的实参等信息

切点表达式语法
在这里插入图片描述

重用切点表示可以通过下面的方式在某一个方法上指定,后
@Before(value = “declarPointCut()”)

@Pointcut(“execution(public int com.atguigu.aop.api.Calculator.add(int,int)))”)
public void declarPointCut() {}

也可以统一放在一个类中,但是此类也需要时bean对象

环绕通知@Around :1.其传入的是ProceedingJoinPoint ,2.其次其更像动态代理方式,可以多方面插入 3.其需要返回返回值和放入参数

.// 使用@Around注解标明环绕通知方法
@Around(value = "com.atguigu.aop.aspect.AtguiguPointCut.transactionPointCut()")
public Object manageTransaction(
    
        // 通过在通知方法形参位置声明ProceedingJoinPoint类型的形参,
        // Spring会将这个类型的对象传给我们
        ProceedingJoinPoint joinPoint) {
    
    // 通过ProceedingJoinPoint对象获取外界调用目标方法时传入的实参数组
    Object[] args = joinPoint.getArgs();
    
    // 通过ProceedingJoinPoint对象获取目标方法的签名对象
    Signature signature = joinPoint.getSignature();
    
    // 通过签名对象获取目标方法的方法名
    String methodName = signature.getName();
    
    // 声明变量用来存储目标方法的返回值
    Object targetMethodReturnValue = null;
    
    try {
    
        // 在目标方法执行前:开启事务(模拟)
        log.debug("[AOP 环绕通知] 开启事务,方法名:" + methodName + ",参数列表:" + Arrays.asList(args));
    
        // 过ProceedingJoinPoint对象调用目标方法
        // 目标方法的返回值一定要返回给外界调用者
        targetMethodReturnValue = joinPoint.proceed(args);
    
        // 在目标方法成功返回后:提交事务(模拟)
        log.debug("[AOP 环绕通知] 提交事务,方法名:" + methodName + ",方法返回值:" + targetMethodReturnValue);
    
    }catch (Throwable e){
    
        // 在目标方法抛异常后:回滚事务(模拟)
        log.debug("[AOP 环绕通知] 回滚事务,方法名:" + methodName + ",异常:" + e.getClass().getName());
    
    }finally {
    
        // 在目标方法最终结束后:释放数据库连接
        log.debug("[AOP 环绕通知] 释放数据库连接,方法名:" + methodName);
    
    }
    
    return targetMethodReturnValue;
}

切面的优先级@Order放在切面类上
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值