spring 6.0

spring6.0

1.认识spring 是一种轻量级的javaEE 框架。

spring  分为广义和狭义之分

 广义:指通过spring framework 为中心和spring技术栈。

狭义:spring framework 我们称之为spring。

1.2spring   核心技术   

spring core 包下 两大核心技术点

 ioc (inversion of contol) 控制反转,ioc是一种思想,是指我们创建资源变成我们索要资源。也就是说我们把bean 对象交给ioc容器进行管理,进行对象的创建,以及依赖关系的维护,可以帮助我们降低耦合,提高程序的可扩展性。

aop (aspect orienten programming) 的简写 称之为面向切面编程。是指用来封装多个类的公共行为,将于业务无关,却与业务模块所公共的调用封装起来,减少代码的重复性。降低耦合性,aop 还解决了系统的公共行为,如日志,事务,权限等。

1.3 spring framework 的特点

     减少侵入性:使用spring进行开发时,spring对代码结构影响小,对领域模型可以做到零污染。对功能开发也就是添加几个注解,不会破坏原有结构,这也就使得代码变得非常清洁,非常优雅。

     ioc

     aop

     容器:我们所说的 ioc 就是一种容器,帮助我们实现bean 的生命周期管理。替代了大量的创建细节,降低了使用门槛,大幅度提高了开发效率。

     组件化:spring实现了大量的组件配置成一个复杂的应用,再spring中可以通过xml 和注解组合这些对象,这使得我们可以有一个功能明确,边界清晰的组件有条不紊的的搭建各种复杂应用。

    一站式: 在ioc 和aop 的基础上我们可以整合各种优秀的开源框架和各种第三方库类。并且spring旗下也覆盖了广泛的领域,很多功能可以进行实现。

1.4 spring 组件

   ​编辑

1.5 spring 版本依赖

    jdk 17 

1.6 具体案例

  1.引入依赖

​编辑

   引入日志​编辑

 ​

引入log4j2.xml 日志配置文件都是固定的。

2.IOC

   ​

DI:依赖注入 依赖注入  用来实现控制反转的思想。

     分为两种方式:

     1.set方法注入。

      2. 构造方法注入。 

案例:

创建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="user" class="org.example.bean.bo.User"/> </beans>

编写代码 :创建do,找到bean的xml 文件   通过上下文 获取bean​编辑

ioc 容器干了什么:

​编辑

Bean 管理说: 是只bean 对象的创建,bean属性中的赋值,以及维护对象间的关系。

 ioc 在spring中的实现:

   在创建bean 之前需要创建ioc容器,创建ioc 容器有两种方法:

  1. beanFactory

  ioc容器实现的基本实现,是spring 面向内部的接口,不提供给开发人员。

   2.ApplicationContext

  是beanFactory 的子接口,提供了更多高级特性,面向spring使用者,几乎所有场合都可以使用,而不是使用beanFactory。​编辑

bean的其他案例,暂不演示。

Bean 的作用域

​编辑

 Bean 的生命周期

1.bean的创建(调用无参构造)

2.bean 的属性赋值

3.bean的后置处理器 调用之前

4.对象初始化 (指定初始化方法)

5.bean 的后置处理器

6.bean 的使用

7.bean的销毁

8.ioc 容器关闭

​编辑

​编辑

FactoryBean

是bean 的一种,一般用来实现复杂的bean 的注入,spring帮我们把复杂的实现细节隐藏,对外暴露简单的bean,供我们使用。如mybaitis 的sqlSessionFactory  就是用FactoryBean 帮我们实现的。

​编辑

 实现FactoryBean 的接口

​编辑

获取bean 即可​编辑 

 2.自动注入

从Java5开始,Java增加了对追截的支持,他是代码中的一种特殊标记,可以在编译、类加载和运行时被读取,执行相应的处理,开发人员可以通过注解在不改变原有代码和逻辑的情况下,在源代码中嵌入补充的信息。

spring 从2.5 版本开始提供了对注解技术的全面支持,我们可以实现自动装配,简化spring的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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.example.bean.bo"/>
</beans>

 ​

常用注解:

@Component 该注解用于描述spring中的bean,他是一个泛化的概念,仅仅表示容器中的一个组件,并且可以作用在应用的任何层次,serice,dao等。使用时标识在相应类上即可。

@Repository

用于将数据访问层Dao 层的类标识为spring中的bean 功能和@component 相似。

@Service 该注解主要用于放在serice 曾 用于标识 业务曾的bean 和component 相似。

@Controller 用于springmvc 中控制层的标识,和component 相同。

@Autowired 注入

1.属性注入

2.set注入

3.构造方法注入

4.形参注入

只支持 构造方法上。

5.只有构造函数,无注解

只有一个参数时,默认不加注解也支持。

6.autowired注解 和qualifier注解联合 指定对应名称注入

@Resouece 注入

全注解开发:

手写IOC

实现细节:

AOP

代理模式:23种代理模式之一,属于结构性模式,他的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再直接调用目标方法,而是通过代理类间接调用。让不属于目标方法核心逻辑的代码从目标方法中抽离出来----解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。

/**
 * @Author liu qi
 * @Description TODO
 * @Date 2023/2/27 21:23
 */
public class AnnoApplicationContextImpl implements IApplicationContext {

    private Map<Class, Object> beanFactory = new HashMap<>();
    private String rootPath;

    @Override
    public Object getBean(Class clazz) {
        return beanFactory.get(clazz);
    }

    /**
     * 基础路径 做扫描包的功能
     *
     * @param basePackagePath
     */
    public AnnoApplicationContextImpl(String basePackagePath) {
        try {
            // . 替换成\
            String packagePath = basePackagePath.replaceAll("\\.", "\\\\");
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packagePath);
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                String filePath = URLDecoder.decode(url.getPath(), StandardCharsets.UTF_8);
                rootPath = filePath.substring(0, filePath.length() - packagePath.length());
                loadClass(new File(filePath));
            }
            loadDi();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void loadDi() throws IllegalAccessException {
        // 1.从beanFactory中获取已经注入的bean
        Set<Map.Entry<Class, Object>> entries = beanFactory.entrySet();
        for (Map.Entry<Class, Object> entry : entries) {
            Object obj = entry.getValue();
            Class<?> aClass = obj.getClass();
            // 获取所有的属性
            Field[] declaredFields = aClass.getDeclaredFields();
            for (Field field : declaredFields) {
                Di annotation = field.getAnnotation(Di.class);
                if (annotation != null) {
                    // 从beanFFactory 中获取值
                    field.setAccessible(true);
                    field.set(obj, beanFactory.get(field.getType()));
                }
            }
        }
    }

    /**
     * 加载类文件
     *
     * @param file
     */
    private void loadClass(File file) {
        //1.判断文件是否时文件夹
        if (file.isDirectory()) {
            File[] childFile = file.listFiles();
            //2.判断文件夹是否为空
            if (childFile == null || childFile.length == 0) {
                return;
            }
            //3.不为空 遍历文件内容
            for (File f : childFile) {
                // 4.判断文件是否时文件夹
                if (f.isDirectory()) {
                    loadClass(f);
                } else {
                    // 5.判断是否时class文件
                    String path = f.getAbsolutePath().substring(rootPath.length() - 1);
                    if (path.endsWith(".class")) {
                        try {
                            // 获取类的全路径
                            String allPath = path.replaceAll("\\\\", ".").replace(".class", "");
                            // 5.1判断是否时接口,接口不进行实例化
                            Class clazz = Class.forName(allPath);
                            if (!clazz.isInterface()) {
                                // 5.2 判断是否带我们标注的注解
                                Annotation annotation = clazz.getAnnotation(Bean.class);
                                if (annotation != null) {
                                    // 6进行实例化
                                    Object bean = clazz.getConstructor().newInstance();
                                    // 6.1 判断bean是否有接口 如果有默认筛入一个
                                    if (clazz.getInterfaces().length > 0) {
                                        beanFactory.put(clazz.getInterfaces()[0], bean);
                                    } else {
                                        beanFactory.put(clazz, bean);
                                    }
                                }
                            }
                        } catch (ClassNotFoundException e) {
                            throw new RuntimeException(e);
                        } catch (InvocationTargetException e) {
                            throw new RuntimeException(e);
                        } catch (InstantiationException e) {
                            throw new RuntimeException(e);
                        } catch (IllegalAccessException e) {
                            throw new RuntimeException(e);
                        } catch (NoSuchMethodException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }
    }
}

静态代理:引入目标对象,通过接口包装目标对象的接口,达到静态代理效果。耦合性差,重复性代码多,灵活性差。如想调用app 对象的 add()方法

但是想在 add() 方法前后执行其他操作。就可以 写一个代理类 如appProxy 里面有addProxy (。。。app.add() ...)方法.。

动态代理测试:不必想静态代理一样只针对一个 类。

public class ProxyFactory { private Object target; public ProxyFactory(Object target) { this.target = target; } public Object getTarget() { ClassLoader classLoader = target.getClass().getClassLoader(); Class<?>[] interfaces = target.getClass().getInterfaces(); InvocationHandler invocationHandler = (proxy, method, args) -> { System.out.println("代理执行前"); Object invoke = method.invoke(target, args); System.out.println("代理执行后"); return invoke; }; return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler); } }

动态代理分类: jdk动态代理,cglib动态代理。

有接口使用jdk动态代理,生成接口实现类。无接口使用cglib动态代理。

aop 切入点扫描格式

常用通知写法:

切入点可重入性:

在同一个切面中直接引入切点方法即可。

不同切面中引用,需要通过全路径名称引用。包名+类名+方法名称

jdbcTemplate 跳过。

spring Test 整合 junit 加载配置文件 跳过

事务:

资源 访问:

数据校验:Validation

提前编译AOT

下载graalvm

认真研究

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

清风扶杨柳

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

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

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

打赏作者

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

抵扣说明:

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

余额充值