赞
踩
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
认真研究
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。