外贸网站建设报价表企业qq一年多少费用
- 作者: 五速梦信息网
- 时间: 2026年04月20日 08:19
当前位置: 首页 > news >正文
外贸网站建设报价表,企业qq一年多少费用,网站规划的基本原则,一般使用的分辨率是多少dpi?文章目录 一、引言1.1 原生web开发中存在哪些问题#xff1f; 二、Spring框架2.1 概念2.2 访问与下载 三、Spring架构组成四、山寨版的Spring容器4.1准备工作4.2 山寨IOC容器4.3 配置文件告诉容器 管理哪些bean4.4 相关类4.5 测试 容器 五、构建Maven项目5.1 新建项目5.2 选择… 文章目录 一、引言1.1 原生web开发中存在哪些问题 二、Spring框架2.1 概念2.2 访问与下载 三、Spring架构组成四、山寨版的Spring容器4.1准备工作4.2 山寨IOC容器4.3 配置文件告诉容器 管理哪些bean4.4 相关类4.5 测试 容器 五、构建Maven项目5.1 新建项目5.2 选择Maven目录5.3 GAV坐标 六、Spring环境搭建6.1 pom.xml中引入Spring常用依赖6.2 创建Spring配置文件 七、Spring工厂编码八、依赖与配置文件详解8.1 Spring依赖关系8.2 schema 九、IoCInversion of Control 控制反转【重点】9.1 项目中强耦合问题9.2 解决方案9.3 IOC 接口 十、DIDependency Injection依赖注入【重点】10.1 概念10.2 Set注入10.2.1 定义目标Bean类型10.2.2 基本类型 字符串类型 日期类型10.2.3 容器类型10.2.4 自建类型 10.3 构造注入【了解】10.3.1 定义目标Bean类型10.3.2 注入 10.4 自动注入 十一、Bean细节11.1 控·制简单对象的单例、多例模式 —– bean的作用域11.2 FactoryBean创建复杂对象11.2.1 实现FactoryBean接口11.2.2 配置spring-context.xml11.2.3 特例 十二、Spring工厂特性12.1 饿汉式创建优势 — 面试题 为什么spring bean 默认是单例12.2 生命周期方法 —- 面试题 spring bean 的声明周期是什么 非常重要12.3 生命周期注解12.4 生命周期阶段 十三、代理设计模式13.1 概念13.2 静态代理设计模式13.3 动态代理设计模式13.3.1 JDK动态代理实现基于接口 代理对象和真实对象的关系 像是兄弟 代理对象 对真实对象进行增强13.3.2 CGlib动态代理实现基于继承 代理对象和真实对象的关系 就像是 父子 十四、面向切面编程【重点】14.1 概念14.2 AOP开发术语14.3 作用14.4 环境搭建14.5 开发流程14.6 AOP小结14.7 通知类【可选】14.8 通配切入点14.9 JDK和CGLIB选择14.10 后处理器14.10.1 后处理器定义14.10.2 配置后处理器14.10.3 bean生命周期14.10.4 动态代理源码(了解) 十五、Spring MyBatis【重点】15.1 配置数据源15.1.1 引入jdbc.properties配置文件15.1.2 整合Spring配置文件和properties配置文件15.1.3 Druid连接池可选参数15.1.4 Druid监控中心15.1.5 测试监控中心 15.2 整合MyBatis15.2.1 导入依赖15.2.2 配置SqlSessionFactory15.2.3 配置MapperScannerConfigurer15.2.4 配置Service 15.3 我的整合步骤 看我的这个步骤 上面的可以不看 十六、事务【重点】16.1 配置DataSourceTransactionManager16.3 事务属性16.3.1 隔离级别16.3.1.1 概念16.3.1.2 特性16.3.1.3 并发问题 16.3.2 传播行为16.3.3 读写性16.3.4 事务超时16.3.5 事务回滚 16.4 编织 十七、注解开发17.1 声明bean17.2 注入(DI)17.3 事务控制17.4 注解所需配置17.5 AOP开发17.5.1 注解使用17.5.2 配置 十八、集成JUnit18.1 导入依赖18.2 编码 十九、个人扩展二十 个人源码解析 一、引言 1.1 原生web开发中存在哪些问题 传统Web开发存在硬编码所造成的过度程序耦合例如Service中作为属性Dao对象。UserDao userdao new UserDaoImpl();部分Java EE API较为复杂使用效率低例如JDBC开发步骤 Servlet的开发步骤。侵入性强移植性差例如DAO实现的更换从Connection到SqlSession。 二、Spring框架 2.1 概念 Spring是一个项目管理框架同时也是一套Java EE解决方案。 Spring是众多优秀设计模式的组合工厂、单例、代理、适配器、包装器、观察者、模板、策略。 Spring并未替代现有框架产品而是将众多框架进行有机整合简化企业级开发俗称胶水框架。 2.2 访问与下载 官方网站https://spring.io/ 下载地址http://repo.spring.io/release/org/springframework/spring/ 三、Spring架构组成 Spring架构由诸多模块组成可分类为 核心技术依赖注入事件资源i18n验证数据绑定类型转换SpELAOP。测试模拟对象TestContext框架Spring MVC测试WebTestClient。数据访问事务DAO支持JDBCORM封送XML。Spring MVC和 Spring WebFlux Web框架。集成远程处理JMSJCAJMX电子邮件任务调度缓存。语言KotlinGroovy动态语言。 Spring架构组成
GroupIdArtifactId说明org.springframeworkspring-beansBeans 支持包含 Groovyorg.springframeworkspring-aop基于代理的AOP支持org.springframeworkspring-aspects基于AspectJ 的切面org.springframeworkspring-context应用上下文运行时包括调度和远程抽象org.springframeworkspring-context-support支持将常见的第三方类库集成到 Spring 应用上下文org.springframeworkspring-core其他模块所依赖的核心模块org.springframeworkspring-expressionSpring 表达式语言SpELorg.springframeworkspring-instrumentJVM 引导的仪表监测器代理org.springframeworkspring-instrument-tomcatTomcat 的仪表监测器代理org.springframeworkspring-jdbc支持包括数据源设置和 JDBC 访问支持org.springframeworkspring-jms支持包括发送/接收JMS消息的助手类org.springframeworkspring-messaging对消息架构和协议的支持org.springframeworkspring-orm对象/关系映射包括对 JPA 和 Hibernate 的支持org.springframeworkspring-oxm对象/XML 映射Object/XML MappingOXMorg.springframeworkspring-test单元测试和集成测试支持组件org.springframeworkspring-tx事务基础组件包括对 DAO 的支持及 JCA 的集成org.springframeworkspring-webweb支持包包括客户端及web远程调用org.springframeworkspring-webmvcREST web 服务及 web 应用的 MVC 实现org.springframeworkspring-webmvc-portlet用于 Portlet 环境的MVC实现org.springframeworkspring-websocketWebSocket 和 SockJS 实现包括对 STOMP 的支持org.springframeworkspring-jclJakarta Commons Logging 日志系统
四、山寨版的Spring容器
创建容器 从容器得到对象 ,而不是程序员自己new 对象从而实现 对象间的解耦
4.1准备工作 UserService public interface UserService {public void addUser();
}UserServiceImpl Overridepublic void addUser() {//使用 spring容器 之前的做法 是 在这里 new 一个 dao 对象 程序员自己new//UserDao userDao new UserJdbcDaoImpl();//现在 需求变了 要使用mybatis 操作数据库 硬编码 耦合度太高 我们希望 不改代码 来改变底层的实现userDao new UserMybatisDaoImpl();userDao.addUser();}UserDao public interface UserDao {void addUser();}UserJdbcDaoImpl public class UserJdbcDaoImpl implements UserDao {Overridepublic void addUser() {System.out.println(使用jdbc来添加用户);}
} UserMybatisDaoImpl public class UserMybatisDaoImpl implements UserDao {Overridepublic void addUser() {System.out.println(使用mybatis来添加用户);}
}原来咱们的做法 没有spring容器的时候 Testpublic void test1(){//使用 spring 容器之前的 做法 自己 newUserService userService new UserServiceImpl();userService.addUser();}4.2 山寨IOC容器
引入spring 容器 从容器中获取对象 MyClassPathXmlApplicationContext package com.glls.java2301.framework;import com.glls.java2301.dao.UserDao;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.;/** date 2023/4/19* desc 山寨版IOC容器 来模拟 真实的 基于XML的 spring 容器/
public class MyClassPathXmlApplicationContext {//用于 存放 解析完 xml文件之后的 bean 的 信息 以 beanId 为key 以BeanDefinition 为值private MapString,BeanDefinition beansMap new HashMap();//这个map 用于存放 spring 容器 创建出来的对象 在容器里面创建出来的对象 叫 bean// 这个map 以 beanId 为 key 以反射创建出来的对象 为值private MapString,Object objectMap new HashMap();public MyClassPathXmlApplicationContext() {}public MyClassPathXmlApplicationContext(String xmlPath) throws DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {//这个构造方法 创建 容器对象 , 创建容器对象的时候 要把容器管理的bean 对象 也创建好//咱们就得告诉 Spring 容器 它所管理的bean对象 有哪些 通常 咱们会通过 xml , 注解 java 配置类//这些方式 告诉 spring 容器 管理的 bean 有哪些 这里 咱们 采用的方式 是 xml 的方式 告知spring 管理// 哪些bean 所以 现在 咱们要做的事情 就是 解析 xml 文件 得到 要创建的 bean 的 信息//1. 解析 xml 文件 得到 bean的信息 把bean 的信息 封装到 BeanDefinition ,每个bean 都会有自己的//beanDefinition 咱们把 很多 bean 的 beanDefinition 放入一个 map 中parseXml(xmlPath);//2.从 beansMap 中 获取bean 的信息 通过反射 创建对象 将创建出来的对象 放入 objectMapcreateObject();//3. di 依赖注入 第二部创建的对象的属性时没有值的di(); //dependency injection 属性注入}//依赖注入 通过反射 调用对象的 set 方法 给对象的属性赋值private void di() throws ClassNotFoundException, InvocationTargetException, IllegalAccessException {SetMap.EntryString, BeanDefinition entrySet beansMap.entrySet();IteratorMap.EntryString, BeanDefinition iterator entrySet.iterator();while (iterator.hasNext()){Map.EntryString, BeanDefinition beanDefinitionEntry iterator.next();String beanId beanDefinitionEntry.getKey();BeanDefinition beanDefinition beanDefinitionEntry.getValue();//得到的bean 的property 集合MapString, PropertyDefinition propsMap beanDefinition.getPropsMap();SetMap.EntryString, PropertyDefinition proSet propsMap.entrySet();IteratorMap.EntryString, PropertyDefinition proIter proSet.iterator();while (proIter.hasNext()){Map.EntryString, PropertyDefinition propertyDefinitionEntry proIter.next();//得到 property 的nameString proName propertyDefinitionEntry.getKey();PropertyDefinition propertyDefinition propertyDefinitionEntry.getValue();//ref 指向 属性对应的beanIdString ref propertyDefinition.getRef();//根据属性名 得到set方法 通过set方法给对象的属性赋值//setUserDaoString setMethodName set proName.substring(0,1).toUpperCase()proName.substring(1);//通过反射 得到方法对象String beanClass beanDefinition.getBeanClass();Class? aClass Class.forName(beanClass);Method[] declaredMethods aClass.getDeclaredMethods();for(Method m:declaredMethods){//判断对象中 有没有这个 set 方法if(m.getName().equals(setMethodName)){//表示 有这个 set 方法//得到对象 给这个对象的属性赋值 要反射调用这个对象的 set 方法Object o objectMap.get(beanId);//得到 set 方法的参数Object para objectMap.get(ref);//反射调用set 方法 给 对象o 的属性赋值// userService.setUserDao(para);m.invoke(o,para);}}}}}//创建对象private void createObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException {//通过反射创建对象 要拿到类的全路径信息SetMap.EntryString, BeanDefinition entrySet beansMap.entrySet();IteratorMap.EntryString, BeanDefinition iterator entrySet.iterator();while (iterator.hasNext()){Map.EntryString, BeanDefinition bean iterator.next();String beanId bean.getKey();BeanDefinition beanDefinition bean.getValue();//得到类的全路径名String beanClass beanDefinition.getBeanClass();//通过反射创建对象Object o Class.forName(beanClass).newInstance();//将创建好的对象 存入 obejctMapobjectMap.put(beanId,o);}}private void parseXml(String xmlPath) throws DocumentException {//读取配置文件 得到流对象InputStream resourceAsStream this.getClass().getClassLoader().getResourceAsStream(xmlPath);//使用dom4j的apiSAXReader saxReader new SAXReader();//得到文档对象Document doc saxReader.read(resourceAsStream);//得到根节点Element rootElement doc.getRootElement();//遍历根节点IteratorElement iterator rootElement.elementIterator();while (iterator.hasNext()){Element bean iterator.next();String beanId bean.attributeValue(id);String beanClass bean.attributeValue(class);//System.out.println(beanId—beanClass);//把解析出来的信息 存入 BeanDefinition 中BeanDefinition beanDefinition new BeanDefinition();beanDefinition.setBeanId(beanId);beanDefinition.setBeanClass(beanClass);//遍历bean 标签的子标签IteratorElement proIterator bean.elementIterator();while (proIterator.hasNext()){Element pro proIterator.next();String proName pro.attributeValue(name);String proRef pro.attributeValue(ref);//将bean 的 子节点 属性信息 封装到 PropertyDefinition 中PropertyDefinition propertyDefinition new PropertyDefinition();propertyDefinition.setName(proName);propertyDefinition.setRef(proRef);//将属性信息 封装到 BeanDefinition 中的 propsMapMapString, PropertyDefinition propsMap beanDefinition.getPropsMap();propsMap.put(proName,propertyDefinition);}//将这个 bean 的定义信息 封装到 beansMapbeansMap.put(beanId,beanDefinition);}}//从容器拿对象的方法public Object getBean(String beanName) {return objectMap.get(beanName);}
} 4.3 配置文件告诉容器 管理哪些bean
beansbean iduserJdbcDao classcom.glls.java2301.dao.impl.UserJdbcDaoImpl /beanbean iduserMybatisDao classcom.glls.java2301.dao.impl.UserMybatisDaoImpl/beanbean iduserService classcom.glls.java2301.service.impl.UserServiceImpl
!– 以后需求变了 不想使用jdbc 来访问数据库了 想使用mybatis 那么仅仅只需要改一下下面的ref 就可以了–property nameuserDao refuserMybatisDao/property/bean/beans4.4 相关类 BeanDefinition package com.glls.java2301.framework;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.HashMap;
import java.util.Map;/** date 2023/4/19* desc bean 的定义信息 来封装bean 的 信息/
Data
AllArgsConstructor
NoArgsConstructor
public class BeanDefinition {//解析xml 解析出来的数据 封装到这个类的对象中private String beanId; // bean 的 名字 bean 在容器中的标识private String beanClass; // 封装bean 的 全路径private MapString,PropertyDefinition propsMap new HashMap();} PropertyDefinition Data
AllArgsConstructor
NoArgsConstructor
public class PropertyDefinition {//property 节点的 name 属性值private String name;//property 节点的 ref 属性值private String ref;}4.5 测试 容器 Testpublic void test2() throws DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {//山寨版的IOC容器// 由容器 来 创建 管理 对象// 创建咱们 的IOC 容器 从容器中 获取 对象 这里 咱们模拟的情况是//容器 创建好了 里面的bean 也创建好了 可以直接用了String config applicationContext.xml;//创建容器对象 告知容器对象扫描的 xml 配置文件 xml 文件中 记录了 spring 容器要管理的 bean的信息MyClassPathXmlApplicationContext applicationContext new MyClassPathXmlApplicationContext(config);//UserDao userDao (UserDao) applicationContext.getBean(userJdbcDao);//UserDao userDao2 (UserDao) applicationContext.getBean(userMybatisDao);UserService userService (UserService) applicationContext.getBean(userService);//userDao.addUser();//userDao2.addUser();userService.addUser();}手写 ioc 容器 – 基于 xml 版本的 目的 理解 ioc 容器
详见 springday1 案例
后面有时间 再带大家写一个 基于注解版本的 理解 bean的生命周期
五、构建Maven项目 5.1 新建项目
使用IDEA打开已创建的文件夹目录
5.2 选择Maven目录
选择Maven项目
5.3 GAV坐标
GAV坐标
六、Spring环境搭建 6.1 pom.xml中引入Spring常用依赖
?xml version1.0 encodingUTF-8?
project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.qf/groupIdartifactIdhello-spring/artifactIdversion1.0-SNAPSHOT/versiondependencies!– Spring常用依赖 –dependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.1.6.RELEASE/version/dependency/dependencies
/project
6.2 创建Spring配置文件 命名无限制约定俗成命名有spring-context.xml、applicationContext.xml、beans.xml ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd/beans七、Spring工厂编码 定义目标Bean类型 public class MyClass{public void show(){System.out.println(HelloWorld);}
}spring-context.xml中的 beans 内部配置bean标签 !– 在 spring 配置文件中使用 bean 标签标签里面添加对应属性就可以实现对象创建 配置实例id:“唯一标识” class需要被创建的目标对象全限定名 创建对象时候默认也是执行无参数构造方法完成对象创建–
bean idmc classcom.qf.spring.part1.factory.MyClass /调用Spring工厂APIApplicationContext接口 public class TestFactory{/** 程序中的对象都交由Spring的ApplicationContext工厂进行创建。/public static void main(String[] args){//1. 读取配置文件中所需创建的bean对象并获得工厂对象ApplicationContext ctx new ClassPathXmlApplicationContext(spring-context.xml);//2. 通过id获取bean对象MyClass mc (MyClass) ctx.getBean(mc);//3. 使用对象mc.show();}
}八、依赖与配置文件详解 Spring框架包含多个模块每个模块各司其职可结合需求引入相关依赖Jar包实现功能。 8.1 Spring依赖关系
Spring常用功能的Jar包依赖关系
注意Jar包彼此存在依赖只需引入最外层Jar即可由Maven自动将相关依赖Jar引入到项目中。
8.2 schema 配置文件中的顶级标签中包含了语义化标签的相关信息 xmlns语义化标签所在的命名空间。xmlns:xsiXMLSchema-instance 标签遵循Schema标签标准。xsi:schemaLocationxsd文件位置用以描述标签语义、属性、取值范围等。 九、IoCInversion of Control 控制反转【重点】 Inverse Of Controll控制反转 反转了依赖关系的满足方式由之前的自己创建依赖对象变为由工厂推送。(变主动为被动即反转) 解决了具有依赖关系的组件之间的强耦合使得项目形态更加稳健 补充 什么是IOC 1.控制反转把对象创建和对象之间的调用过程交给 Spring 进行管理 2.使用 IOC 目的为了耦合度降低 3.入门案例就是 IOC 实现 IOC 底层原理 xml 解析、工厂模式、反射 9.1 项目中强耦合问题
public class UserDAOImpl implements UserDAO{….}public class UserServiceImpl implements UserService {// !!!强耦合了UserDAOImpl!!!,使得UserServiceImpl变得不稳健!!private UserDAO userDAO new UserDAOImpl();Overridepublic User queryUser() {return userDAO.queryUser();}….
}9.2 解决方案
// 不引用任何一个具体的组件(实现类)在需要其他组件的位置预留存取值入口(set/get)
public class UserServiceImpl implements UserService {// !!!不再耦合任何DAO实现!!!,消除不稳健因素!!private UserDAO userDAO// 为userDAO定义set/get,允许userDAO属性接收spring赋值//Getters And SettersOverridepublic User queryUser() {return userDAO.queryUser();}….
}bean iduserDAO classcom.qf.spring.part1.injection.UserDaoImpl/bean
!– UserServiceImpl组件 –
bean iduserService classcom.qf.spring.part1.injection.UserServiceImpl!– 由spring为userDAO属性赋值值为iduserDAO的bean –property nameuserDAO refuserDAO/
/bean此时如果需要更换其他UserDAO实现类则UserServiceImpl不用任何改动 则此时的UserServiceImpl组件变得更加稳健 9.3 IOC 接口
1.IOC 思想基于 IOC 容器完成IOC 容器底层就是对象工厂
2.Spring 提供 IOC 容器实现两种方式两个接口 BeanFactoryIOC 容器基本实现是 Spring 内部的使用接口不提供开发人员进行使用 加载配置文件时候不会创建对象在获取对象使用才去创建对象 ApplicationContextBeanFactory 接口的子接口提供更多更强大的功能一般由开发人 员进行使用 加载配置文件时候就会把在配置文件对象进行创建 3.IOC操作bean管理
Bean的管理指的是两个操作1.Spring创建对象 2.Spring注入属性
Bean的常见的管理操作有两种方式1.基于 xml 配置文件方式实现 2.基于注解方式实现
十、DIDependency Injection依赖注入【重点】 10.1 概念 在Spring创建对象的同时为其属性赋值称之为依赖注入。 10.2 Set注入 创建对象时Spring工厂会通过Set方法为对象的属性赋值。 10.2.1 定义目标Bean类型
public class User {private Integer id;private String password;private String sex;private Integer age;private Date bornDate;private String[] hobbys;private SetString phones;private ListString names;private MapString,String countries;private Properties files;//Getters And Setters
}10.2.2 基本类型 字符串类型 日期类型
bean idu1 classcom.qf.spring.part1.injection.User!–base field–property nameid value1001 /property namepassword value123456 /property namesex valuemale /property nameage value20 /property namebornDate value1990/1/1 /!–注意格式/–
/bean10.2.3 容器类型
bean idu1 classcom.qf.spring.part1.injection.User !–Array–property namehobbysarrayvalueRun/valuevalueSwim/valuevalueClimb/value/array/property!–Set–property namephonessetvalue13777777777/valuevalue13888888888/valuevalue13999999999/value/set/property!–List–property namenameslistvaluetom/valuevaluejack/valuevaluemarry/value/list/property!–Map–property namecountriesmapentry keyCN valueChina /entry keyUS valueAmerica /entry keyKR valueKorea //map/property!–Properties–property namefilespropsprop keyfirstOne/propprop keysecondTwo/propprop keythirdThree/prop/props/property
/bean10.2.4 自建类型
!–次要bean被作为属性–
bean idaddr classcom.qf.spring.part1.injection.Addressproperty nameposition value北京市海淀区 /property namezipCode value100001 /
/bean!–主要bean操作的主体–
bean idu2 classcom.qf.spring.part1.injection.Userproperty nameaddress refaddr /!–address属性引用addr对象–
/bean!–次要bean被作为属性–
bean iduserDao classcom.qf.spring.part1.injection.UserDaoImpl /!–主要bean操作的主体–
bean iduserService classcom.qf.spring.part1.injection.UserServiceImplproperty nameud refuserDao /!–ud属性引用userDao对象–
/bean10.3 构造注入【了解】 创建对象时Spring工厂会通过构造方法为对象的属性赋值。 10.3.1 定义目标Bean类型
public class Student {private Integer id;private String name;private String sex;private Integer age;//Constructorspublic Student(Integer id , String name , String sex , Integer age){this.id id;this.name name;this.sex sex;this.age age;}
}10.3.2 注入 !–构造注入–
bean idu3 classcom.qf.zcg.spring.day1.t2.ioc.Studentconstructor-arg nameid value1234 / !– 除标签名称有变化其他均和Set注入一致 –constructor-arg namename valuetom /constructor-arg nameage value20 /constructor-arg namesex valuemale /
/bean10.4 自动注入 不用在配置中 指定为哪个属性赋值及赋什么值. 由spring自动根据某个 “原则” 在工厂中查找一个bean为属性注入属性值 也叫自动装配 根据装配规则 属性名和属性类型 spring 自动将匹配的属性值进行注入
演示过程
1.根据属性名称自动注入在 bean 标签 使用 autowire 配置自动装配autowire 属性 常用两个值byName 根据属性名称注入 注入值的 bean 的 id 和 类的属性名一样byType 根据属性类型注入 如果 容器内 有多个这个类型的bean 那么 容器如果不知道注入哪一个 就会报错public class UserServiceImpl implements UserService {private UserDAO userDAO//Getters And Setters….
}bean iduserDao classcom.qf.spring.part1.injection.UserDaoImpl /
!– 为UserServiceImpl中的属性基于类型自动注入值 –
bean iduserService classcom.qf.spring.part1.injection.UserServiceImpl autowirebyType/beanbean iduserDao classcom.qf.spring.part1.injection.UserDaoImpl /
!– 为UserServiceImpl中的属性基于名字自动注入值 –
bean iduserService classcom.qf.spring.part1.injection.UserServiceImpl autowirebyName/bean十一、Bean细节 11.1 控·制简单对象的单例、多例模式 —– bean的作用域
在spring 容器里 设置 bean 实例 是 单例 还是 多例 默认情况下 bean 是 单例的 配置 bean scope“singleton | prototype” / !–singleton默认每次调用工厂得到的都是同一个对象。 加载 spring 配置文件时候就会创建单实例对象prototype每次调用工厂都会创建新的对象。 不是在加载 spring 配置文件时候创建 对象在调用
getBean 方法时候创建多实例对象–
bean idmc classcom.qf.zcg.spring.day1.t1.basic.MyClass scopesingleton / 注意需要根据场景决定对象的单例、多例模式。可以共用Service、DAO、SqlSessionFactory或者是所有的工厂。不可共用Connection、SqlSession、ShoppingCart。
11.2 FactoryBean创建复杂对象
注意 和 前面的 BeanFactory 的区别
补充spring有两种类型的bean 一种是 普通bean 另外一种是 工厂bean (FactoryBean)
普通的bean : 在配置文件中定义的bean的类型 就是返回类型
工厂bean 在配置文件中定义的bean类型可以和返回的bean类型不一样 作用让Spring可以创建复杂对象、或者无法直接通过反射创建的对象。 FactoryBean解决复杂对象创建
11.2.1 实现FactoryBean接口
接口方法描述
注意isSingleton方法的返回值需根据所创建对象的特点决定返回true/false。例如Connection 不应该被多个用户共享返回false。例如SqlSessionFactory 重量级资源不该过多创建返回true。
11.2.2 配置spring-context.xml
配置与获取方式
11.2.3 特例
获取FactoryBean接口的实现类对象而非getObject()所生产的对象。
十二、Spring工厂特性 12.1 饿汉式创建优势 — 面试题 为什么spring bean 默认是单例 工厂创建之后会将Spring配置文件中的所有对象都创建完成饿汉式。 提高程序运行效率。避免多次IO减少对象创建时间。概念接近连接池一次性创建好使用时直接获取 如果默认是多例bean 首先创建多例bean 会消耗资源 还会占用堆空间 12.2 生命周期方法 —- 面试题 spring bean 的声明周期是什么 非常重要 什么生命周期 bean 对象从创建到销毁的过程 步骤 bean 的实例化 通过构造方法创建bean 的实例 默认是无参构造给bean 的属性赋值 调用 set 方法执行初始化的方法 需要配置初始化方法得到完整的bean 对象 这时的bean 对象才能够使用销毁bean 需要配置 销毁的方法
要考虑 bean 的后置处理器 BeanPostProcessor
创建一个类实现BeanPostProcessor 重写 他的两个方法
public class MyBeanPost implements BeanPostProcessor {Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(在bean 初始化之前执行);return bean;}Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(在bean初始化之后执行);if(bean instanceof User){User user (User) bean;user.setName(貂蝉);return user;}return bean;}
}在配置文件 配置这个 bean bean idmyPostProcessor classcom.qf.postprocessor.MyBeanPost/bean总结 面试答案
bean 的实例化 通过构造方法创建bean 的实例 默认是无参构造给bean 的属性赋值把 bean 的 实例 传递给 bean的后置处理器的方法 postProcessBeforeInitialization执行初始化的方法把 bean 的 实例 传递给 bean的后置处理器的方法 postProcessAfterInitialization得到完整的bean 对象 这时的bean 对象才能够使用销毁bean 当容器关闭的时候 调用销毁的方法 自定义初始化方法添加“init-method”属性Spring则会在创建对象之后调用此方法。 自定义销毁方法添加“destroy-method”属性Spring则会在销毁对象之前调用此方法。 销毁工厂的close()方法被调用之后Spring会毁掉所有已创建的单例对象。 分类Singleton对象由Spring容器销毁、Prototype对象由JVM销毁。 12.3 生命周期注解 初始化注解、销毁注解 import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;PostConstruct //初始化
public void init(){System.out.println(init method executed);
}PreDestroy //销毁
public void destroy(){System.out.println(destroy method executed);
}12.4 生命周期阶段 单例beansingleton 随工厂启动创建 》 构造方法 》 set方法(注入值) 》 init(初始化) 》 构建完成 》随工厂关闭销毁 多例beanprototype 被使用时创建 》 构造方法 》 set方法(注入值) 》 init(初始化) 》 构建完成 》JVM垃圾回收销毁 十三、代理设计模式 13.1 概念 将核心功能与辅助功能事务、日志、性能监控代码分离达到核心业务功能更纯粹、辅助业务功能可复用。 功能分离
13.2 静态代理设计模式 通过代理类的对象为原始类的对象目标类的对象添加辅助功能更容易更换代理实现类、利于维护。 静态代理
代理类 实现原始类相同接口 添加辅助功能 调用原始类的业务方法。静态代理的问题 代理类数量过多不利于项目的管理。多个代理类的辅助功能代码冗余修改时维护性差。
13.3 动态代理设计模式 动态创建代理类的对象为原始类的对象添加辅助功能。 13.3.1 JDK动态代理实现基于接口 代理对象和真实对象的关系 像是兄弟 代理对象 对真实对象进行增强
//目标
final OrderService os new OrderServiceImpl();
//额外功能
InvocationHandler handler new InvocationHandler(){//1.设置回调函数额外功能代码Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {System.out.println(start…);method.invoke(os, args);System.out.println(end…);return null;}
};
//2.创建动态代理类
Object proxyObj Proxy.newProxyInstance(ClassLoader , Interfaces , InvocationHandler);个人代码
接口
public interface Marry {public void marry();public int money();}真实对象
public class You implements Marry {Overridepublic void marry() {System.out.println(终身大事);}Overridepublic int money() {int num 10;System.out.println(花了num块钱);return num;}
}封装的一个工具类
public class JdkProxy implements InvocationHandler {private Object target; //真实对象 被代理的对象//把真实对象传进来 返回代理对象public Object getProxy(Object target){this.target target;return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}//对真实对象的功能增强Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(准备工作);Object result method.invoke(target, args);System.out.println(收尾工作);if(target instanceof Marry){return 100;}return result;}
}测试
public class TestJdkProxy {public static void main(String[] args) {//真实对象You you new You();JdkProxy jdkProxy new JdkProxy();//得到代理对象Marry proxy (Marry) jdkProxy.getProxy(you);//调用代理对象的方法proxy.marry();int money proxy.money();System.out.println(money);}
} 13.3.2 CGlib动态代理实现基于继承 代理对象和真实对象的关系 就像是 父子
final OrderService os new OrderServiceImpl();
Enhancer cnh new Enhancer();//1.创建字节码曾强对象
enh.setSuperclass(os.getClass());//2.设置父类等价于实现原始类接口
enh.setCallback(new InvocationHandler(){//3.设置回调函数额外功能代码Overridepublic Object invoke(Object proxy , Method method, Object[] args) throws Throwable{System.out.println(start…);Object ret method.invoke(os,args);System.out.println(end…);return ret;}
});
OrderService proxy (OrderService)enh.create();//4.创建动态代理类
proxy,createOrder();个人代码
真实对象
public class You {public void marry() {System.out.println(终身大事);}public int money() {int num 10;System.out.println(花了num块钱);return num;}}工具类 封装得到代理对象的方法 和 回调方法
package com.qf.proxy.cglibproxy;import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.InvocationHandler;import java.lang.reflect.Method;public class CglibProxy implements InvocationHandler {//真实对象private Object target;//传入真实对象 得到代理对象public Object getProxy(Object target){this.target target;Enhancer enhancer new Enhancer();//1.创建字节码曾强对象enhancer.setSuperclass(target.getClass());//2.设置父类等价于实现原始类接口//设置回调函数enhancer.setCallback(this);//返回代理对象return enhancer.create();}//真实对象方法增强Overridepublic Object invoke(Object o, Method method, Object[] objects) throws Throwable {System.out.println(准备工作);Object result method.invoke(target, objects);System.out.println(收尾工作);return result;}
}
测试
package com.qf.proxy.cglibproxy;public class TestCglibProxy {public static void main(String[] args) {//真实对象You you new You();//工具类对象CglibProxy cglibProxy new CglibProxy();//得到代理对象You proxy (You) cglibProxy.getProxy(you);proxy.marry();}
}
十四、面向切面编程【重点】 14.1 概念 AOPAspect Oriented Programming即面向切面编程利用一种称为横切的技术剖开封装的对象内部并将那些影响了多个类的公共行为封装到一个可重用模块并将其命名为Aspect即切面。所谓切面简单说就是那些与业务无关却为业务模块所共同调用的逻辑或责任封装起来便于减少系统的重复代码降低模块之间的耦合度并有利于未来的可操作性和可维护性。 什么是AOP
1.面向切面编程 利用AOP 可以对业务逻辑的各个部分进行隔离 从而使业务逻辑的各部分之间 耦合度降低提高程序的可重用性提好了开发效率通俗的讲 可以实现不修改源代码的方式在核心业务里面 添加新的功能
AOP 底层的原理 就是 动态代理 真正干活的 bean 是 代理bean , 代理bean 对真实bean 功能增强
14.2 AOP开发术语 连接点(Joinpoint)连接点是程序类中客观存在的方法可被Spring拦截并切入内容。说白了 类中的哪些方法 可以被增强 这些方法 就称为是 连接点切入点(Pointcut)被Spring切入连接点。真正被增强的方法 称为 切入点通知、增强(Advice)可以为切入点添加额外功能分为前置通知、后置通知、异常通知、环绕通知最终通知等。实际增强的逻辑部分 称为通知增强目标对象(Target)代理的目标对象 真实对象引介(Introduction)一种特殊的增强可在运行期为类动态添加Field和Method。织入(Weaving)把通知应用到具体的类进而创建新的代理类的过程。代理(Proxy)被AOP织入通知后产生的结果类。切面(Aspect)由切点和通知组成将横切逻辑织入切面所指定的连接点中。是一个动作 把通知 应用到 切入点的过程 14.3 作用 Spring的AOP编程即是通过动态代理类为原始类的方法添加辅助功能。 14.4 环境搭建 引入AOP相关依赖 dependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion5.1.6.RELEASE/version
/dependencyspring-context.xml引入AOP命名空间 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:phttp://www.springframework.org/schema/pxmlns:aophttp://www.springframework.org/schema/aopxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd/beans14.5 开发流程 定义原始类 package com.qf.aaron.aop.basic;public interface UserService {public void save();
}package com.qf.aaron.aop.basic;public class UserServiceImpl implements UserService {public void save() {System.out.println(save method executed…);}
}下面是 基于 Schema-based 的 aop实现方式 得认识 四种通知 MyBeforeAdvice 前置通知
AfterReturningAdvice 后置返回通知
注意 Schema-based 没有最终通知
MethodInterceptor 环绕通知
ThrowsAdvice 异常通知 定义通知类添加额外功能 package com.qf.aaron.aop.basic;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;public class MyAdvice implements MethodBeforeAdvice { //实现前置通知接口public void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(before advice executed…);}
}定义bean标签 !–原始对象–
bean idus classcom.qf.aaron.aop.basic.UserServiceImpl /!–辅助对象–
bean idmyAdvice classcom.qf.aaron.aop.basic.MyAdvice /定义切入点PointCut 形成切面Aspect aop:config!–切点–aop:pointcut idmyPointCut expressionexecution( save()) /
/aop:configaop:config!–组装切面 –aop:advisor advice-refmyAdvice pointcut-refmyPointCut /
/aop:config下面是基于 AspectJ 的 AOP 实现方式
方式1 基于 xml 的配置
创建 通知类
package com.qf.aspectjadvice;import org.aspectj.lang.ProceedingJoinPoint;/*** ClassName : MyAspectJAdvice* Description : AspectJ 的 通知类 无需实现接口/
public class MyAspectJAdvice {public void mybefore(){System.out.println(aspectj的前置通知);}public void myafter(){System.out.println(aspectj的后置通知);}public Object myaround(ProceedingJoinPoint p) throws Throwable {System.out.println(环绕前置);Object result p.proceed();System.out.println(环绕后置);return result;}
}
xml 配置
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!–基于注解的形式 管理 bean–!–扫描 com.qf 下的全部组件–context:component-scan base-packagecom.qf/context:component-scan!–了解 基于 AspectJ 的 xml 的 AOP实现 配置–bean idmyaspectj classcom.qf.aspectjadvice.MyAspectJAdvice/beanaop:configaop:aspect refmyaspectjaop:pointcut idaspectjpoint1 expressionexecution( save(..))//aop:aspectaop:aspect refmyaspectjaop:pointcut idaspectjpoint2 expressionexecution(* com.qf.service.impl.OrderServiceImpl.save(..))//aop:aspectaop:aspect refmyaspectjaop:before methodmybefore pointcut-refaspectjpoint1/aop:beforeaop:after methodmyafter pointcut-refaspectjpoint1/aop:afteraop:around methodmyaround pointcut-refaspectjpoint2/aop:around/aop:aspect/aop:config/beans测试 Testpublic void test2(){// 基于 Aspectj 的 xml 的 AOP 了解 看得懂ClassPathXmlApplicationContext applicationContext new ClassPathXmlApplicationContext(beans2.xml);UserService userService applicationContext.getBean(userService, UserService.class);OrderService orderService applicationContext.getBean(orderService, OrderService.class);userService.save();//userService.delete(1);Order order new Order(1, 订单描述);//orderService.save(order);}方式2 aspectj 基于 注解的aop 实现 要求掌握
配置文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!–基于注解的形式 管理 bean–!–扫描 com.qf 下的全部组件–context:component-scan base-packagecom.qf/context:component-scan!–掌握 基于 AspectJ 的 注解 的 AOP实现 配置–aop:aspectj-autoproxy/aop:aspectj-autoproxy/beans通知类
package com.qf.aspectaannotation;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;Aspect
Component
public class AspectjAnnotationAdvice {// Before 表示前置通知Before(execution(* save(..)))public void before(){System.out.println(基于aspectj注解形式的前置通知要求大家掌握);}
}
测试效果
14.6 AOP小结 通过AOP提供的编码流程更便利的定制切面更方便的定制了动态代理。 进而彻底解决了辅助功能冗余的问题 业务类中职责单一性得到更好保障 辅助功能也有很好的复用性。 14.7 通知类【可选】 定义通知类达到通知效果 前置通知MethodBeforeAdvice后置通知AfterAdvice后置通知AfterReturningAdvice //有异常不执行方法会因异常而结束无返回值异常通知ThrowsAdvice环绕通知MethodInterceptor没有必要把通知的执行顺序 记得非常精确 因为 spring 新版本 5 和 之前的旧版本 通知的执行顺序 不一样
14.8 通配切入点 根据表达式通配切入点 !–匹配参数–
aop:pointcut idmyPointCut expressionexecution(* (com.qf.aaron.aop.basic.User)) /
!–匹配方法名无参–
aop:pointcut idmyPointCut expressionexecution( save()) /
!–匹配方法名任意参数–
aop:pointcut idmyPointCut expressionexecution(* save(..)) /
!–匹配返回值类型–
aop:pointcut idmyPointCut expressionexecution(com.qf.aaron.aop.basic.User (..)) /
!–匹配类名–
aop:pointcut idmyPointCut expressionexecution( com.qf.aaron.aop.basic.UserServiceImpl.(..)) /
!–匹配包名–
aop:pointcut idmyPointCut expressionexecution( com.qf.aaron.aop.basic..(..)) /
!–匹配包名、以及子包名–
aop:pointcut idmyPointCut expressionexecution(* com.qf.aaron.aop...(..)) /切入点表达式expression 知道对哪个类的那个方法进行增强
语法结构 execution([权限修饰符] [返回值类型] [类全路径] [方法名称] [参数列表])
14.9 JDK和CGLIB选择 spring底层包含了jdk代理和cglib代理两种动态代理生成机制 基本规则是目标业务类如果有接口则用JDK代理没有接口则用CGLib代理 class DefaultAopProxyFactory{// 该方法中明确定义了 JDK代理和CGLib代理的选取规则// 基本规则是目标业务类如果有接口则用JDK代理没有接口则用CGLib代理public AopProxy createAopProxy(){…}
}14.10 后处理器 spring中定义了很多后处理器 每个bean在创建完成之前 都会有一个后处理过程即再加工对bean做出相关改变和调整 spring-AOP中就有一个专门的后处理器负责通过原始业务组件(Service),再加工得到一个代理组件。 常用后处理器[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7iaN9bjA-1682258194560)(https://gllspictures.oss-cn-beijing.aliyuncs.com/img/系统后处理器.jpg)]
14.10.1 后处理器定义
/*** 定义bean后处理器* 作用在bean的创建之后进行再加工/
public class MyBeanPostProcessor implements BeanPostProcessor{/** 在bean的init方法之前执行* param bean 原始的bean对象* param beanName* return* throws BeansException/public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println(后处理器 在init之前执行~~~bean.getClass());return bean;}/** 在bean的init方法之后执行* param bean postProcessBeforeInitialization返回的bean* param beanName* return* throws BeansException/Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(后处理器 在init之后执行~~~bean.getClass());return bean;// 此处的返回是 getBean() 最终的返回值}
}14.10.2 配置后处理器
!– 配置后处理器,将对工厂中所有的bean声明周期进行干预 –
bean classcom.qianfeng.beanpostprocessor.MyBeanPostProcessor/bean14.10.3 bean生命周期 构造 》 注入属性 满足依赖 》 后处理器前置过程 》 初始化 》后处理器后置过程 》 返回 》 销毁 记住 记住 记住 记住 记住 记住
1.如果是单例 bean 随着容器的创建而创建 即 实例化多例bean 是 获取的时候 实例化
2.属性注入
3.后处理器前置过程 即在初始化方法之前执行的 方法 postProcessBeforeInitialization
4.初始化方法
5.后处理器后置过程 即在初始化方法之后执行的 方法 postProcessAfterInitialization aop动态代理就在这一步
6.得到最终的 bean
7.销毁
14.10.4 动态代理源码(了解)
// AbstractAutoProxyCreator是 AspectJAwareAdvisorAutoProxyCreator的父类
// 该后处理器类中的 wrapIfNecessary方法即动态代理生成过程
AbstractAutoProxyCreator#postProcessAfterInitialization(Object bean, String beanName){if (!this.earlyProxyReferences.contains(cacheKey)) {// 开始动态定制代理return wrapIfNecessary(bean, beanName, cacheKey);}
}十五、Spring MyBatis【重点】 15.1 配置数据源 将数据源配置到项目中 15.1.1 引入jdbc.properties配置文件
#jdbc.properties
jdbc.driverClasscom.mysql.jdbc.Driver
jdbc.urljdbc:mysql://localhost:3306/mydb?useUnicodetruecharacterEncodingUTF-8
jdbc.usernameroot
jdbc.password12345615.1.2 整合Spring配置文件和properties配置文件
!–spring-context.xml–
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:contexthttp://www.springframework.org/schema/contextxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!–配置文件参数化参数占位符–context:property-placeholder locationclasspath:jdbc.properties /!–与PooledDataSource集成二选一–bean iddataSource classorg.apache.ibatis.datasource.pooled.PooledDataSourceproperty namedriver value\({driverClass}/property nameurl value\){url}/property nameusername value\({username}/property namepassword value\){password}//bean!–与DruidDataSource集成二选一–bean iddataSource classcom.alibaba.druid.pool.DruidDataSource init-methodinit destroy-methodclose!–基本配置–property namedriverClassName value\({jdbc.driverClass}/property nameurl value\){jdbc.url}/property nameusername value\({jdbc.username}/property namepassword value\){jdbc.password}//bean
/bean15.1.3 Druid连接池可选参数
bean iddataSource classcom.alibaba.druid.pool.DruidDataSource init-methodinit destroy-methodclose!–基本配置–property namedriverClassName value\({jdbc.driverClass}/property nameurl value\){jdbc.url}/property nameusername value\({jdbc.username}/property namepassword value\){jdbc.password}/!– 配置初始化大小、最小、最大 –property nameinitialSize value\({jdbc.init}/property nameminIdle value\){jdbc.minIdle}/property namemaxActive value${jdbc.maxActive}/!– 配置获取连接等待超时的时间 –property namemaxWait value60000/!– 配置间隔多久才进行一次检测检测需要关闭的空闲连接单位是毫秒 –property nametimeBetweenEvictionRunsMillis value60000/!– 配置一个连接在池中最小生存的时间单位是毫秒 –property nameminEvictableIdleTimeMillis value300000/
/bean15.1.4 Druid监控中心
!–web.xml–
servletservlet-nameDruidStatView/servlet-nameservlet-classcom.alibaba.druid.support.http.StatViewServlet/servlet-class
/servlet
servlet-mappingservlet-nameDruidStatView/servlet-nameurl-pattern/druid//url-pattern
/servlet-mapping15.1.5 测试监控中心 配置tomcat并访问protocol://ip:port/project/druid/index.html 15.2 整合MyBatis 将 SqlSessionFactory、DAO、Service 配置到项目中 15.2.1 导入依赖
!– spring-jdbc –
dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.1.6.RELEASE/version
/dependency!– springmybatis集成依赖 –
dependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion1.3.1/version
/dependency15.2.2 配置SqlSessionFactory
!– 工厂bean生成SqlSessionFactory –
bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean!– 注入连接池 –property namedataSource refdataSource/property!– 注入dao-mapper文件信息 ,如果映射文件和dao接口 同包且同名则此配置可省略–property namemapperLocationslistvalueclasspath:com/qf/spring/dao/.xml/value/list/property!– 为 dao-mapper文件中的实体 定义缺省包路径 如select idqueryAll resultTypeUser 中 User类可以不定义包–property nametypeAliasesPackage valuecom.qf.entity/property
/bean15.2.3 配置MapperScannerConfigurer 管理DAO实现类的创建并创建DAO对象存入工厂管理 扫描所有DAO接口,去构建DAO实现 将DAO实现存入工厂管理 DAO实现对象在工厂中的id是“首字母小写的-接口的类名” 例如UserDAOuserDAO , OrderDAOorderDAO !– mapperScannerConfigurer –
bean idmapperScannerConfigurer9 classorg.mybatis.spring.mapper.MapperScannerConfigurer!– dao接口所在的包 如果有多个包可以用逗号或分号分隔 property namebasePackage valuecom.a.dao,com.b.dao/property–property namebasePackage valuecom.qf.spring.dao/property!– 如果工厂中只有一个SqlSessionFactory的bean此配置可省略 –property namesqlSessionFactoryBeanName valuesqlSessionFactory/property
/bean15.2.4 配置Service
bean iduserService classcom.qf.spring.service.UserServiceImpl!– 注意ref中的值是对应DAO接口的首字母小写的接口名 –property nameuserDAO refuserDAO/property
/bean15.3 我的整合步骤 看我的这个步骤 上面的可以不看
1.添加依赖
?xml version1.0 encodingUTF-8?project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.qf/groupIdartifactIdsm/artifactIdversion1.0-SNAPSHOT/versionpackagingwar/packagingnamesm Maven Webapp/name!– FIXME change it to the projects website –urlhttp://www.example.com/urlpropertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.target/propertiesdependenciesdependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-context/artifactIdversion5.2.0.RELEASE/version/dependencydependencygroupIdorg.springframework/groupIdartifactIdspring-aspects/artifactIdversion5.2.0.RELEASE/version/dependency!–MyBatis核心依赖–dependencygroupIdorg.mybatis/groupIdartifactIdmybatis/artifactIdversion3.4.6/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion8.0.21/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion1.18.20/version/dependency!– log4j日志依赖 https://mvnrepository.com/artifact/log4j/log4j –dependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion1.2.17/version/dependency!– spring-jdbc –dependencygroupIdorg.springframework/groupIdartifactIdspring-jdbc/artifactIdversion5.2.0.RELEASE/version/dependency!– springmybatis集成依赖 –dependencygroupIdorg.mybatis/groupIdartifactIdmybatis-spring/artifactIdversion1.3.2/version/dependency!– https://mvnrepository.com/artifact/com.alibaba/druid –dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.16/version/dependency/dependenciesbuildfinalNamesm/finalNamepluginManagement!– lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) –pluginspluginartifactIdmaven-clean-plugin/artifactIdversion3.1.0/version/plugin!– see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging –pluginartifactIdmaven-resources-plugin/artifactIdversion3.0.2/version/pluginpluginartifactIdmaven-compiler-plugin/artifactIdversion3.8.0/version/pluginpluginartifactIdmaven-surefire-plugin/artifactIdversion2.22.1/version/pluginpluginartifactIdmaven-war-plugin/artifactIdversion3.2.2/version/pluginpluginartifactIdmaven-install-plugin/artifactIdversion2.5.2/version/pluginpluginartifactIdmaven-deploy-plugin/artifactIdversion2.8.2/version/plugin/plugins/pluginManagement!– 如果不添加此节点src/main/java目录下的所有配置文件都会被漏掉。 –resourcesresourcedirectorysrc/main/java/directoryincludesinclude**/.xml/include/includes/resourceresourcedirectorysrc/main/resources/directoryincludesinclude/*.xml/includeinclude/.properties/includeinclude**/.ini/include/includes/resource/resources/build
/project
2.spring的配置文件
准备数据源配置文件 db.properties
jdbc.drivercom.mysql.cj.jdbc.Driver
jdbc.urljdbc:mysql://localhost:3306/ssm?characterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghairewriteBatchedStatementstrue
jdbc.usernameroot
jdbc.password123456?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!–基于注解的形式 管理 bean–!–扫描 com.qf 下的全部组件–context:component-scan base-packagecom.qf/context:component-scan!–掌握 基于 AspectJ 的 注解 的 AOP实现 配置–aop:aspectj-autoproxy/aop:aspectj-autoproxy!–配置文件参数化参数占位符–context:property-placeholder locationclasspath:db.properties /bean iddataSource classcom.alibaba.druid.pool.DruidDataSource init-methodinit destroy-methodclose!–基本配置–property namedriverClassName value\({jdbc.driver}/property nameurl value\){jdbc.url}/property nameusername value\({jdbc.username}/property namepassword value\){jdbc.password}/!– 配置获取连接等待超时的时间 –property namemaxWait value60000/!– 配置间隔多久才进行一次检测检测需要关闭的空闲连接单位是毫秒 –property nametimeBetweenEvictionRunsMillis value60000/!– 配置一个连接在池中最小生存的时间单位是毫秒 –property nameminEvictableIdleTimeMillis value300000//bean!– 工厂bean生成SqlSessionFactory –bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean!–数据源属性–property namedataSource refdataSource/property!–mybatis的配置文件–property nameconfigLocation valueclasspath:mybatis-config.xml/property/beanbean classorg.mybatis.spring.mapper.MapperScannerConfigurer!–扫描mapper 接口 自动创建mapper层代理对象 交给spring管理–property namebasePackage valuecom.qf.mapper/propertyproperty namesqlSessionFactoryBeanName valuesqlSessionFactory/property/bean/beansmybatis的配置文件
?xml version1.0 encodingUTF-8 ?
!DOCTYPE configuration PUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtd
configurationtypeAliases!–自动扫描包将原类名作为别名–package namecom.qf.pojo //typeAliasesmappers!–扫描xml 映射文件–package namecom.qf.mapper//mappers
/configuration整合 logback 日志
添加依赖 !–logback 日志–dependencygroupIdorg.slf4j/groupIdartifactIdslf4j-api/artifactIdversion1.7.25/version/dependencydependencygroupIdch.qos.logback/groupIdartifactIdlogback-core/artifactIdversion1.2.3/version/dependencydependencygroupIdch.qos.logback/groupIdartifactIdlogback-classic/artifactIdversion1.2.3/version/dependencydependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion1.2.17/version/dependencydependencygroupIdorg.logback-extensions/groupIdartifactIdlogback-ext-spring/artifactIdversion0.1.4/version/dependency添加日志的配置文件 logback.xml
?xml version1.0 encodingUTF-8?
configurationappender namestdout classch.qos.logback.core.ConsoleAppenderTargetSystem.out/TargetEncodingUTF-8/Encodingencoderpattern%d{yyyy-MM-dd_HH:mm:ss.SSS} %5p [%t] [%c{1}]:%L - %m%n/pattern/encoder/appenderappender namelogfileclassch.qos.logback.core.rolling.RollingFileAppenderEncodingUTF-8/Encodingencoderpattern%d %p [%t] [%c]:%L - %m%n/pattern/encoderfilter classch.qos.logback.classic.filter.ThresholdFilterlevelDEBUG/level/filterrollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicyfileNamePatternlog/%d{yyyy-MM-dd-HH.log}/fileNamePattern/rollingPolicy/appenderlogger nameorg.springframework levelWARN /logger nameorg.springframework.remoting levelWARN /logger nameorg.springframework.scheduling.quartz levelWARN /logger nameorg.springframework.data.jpa levelDEBUG /logger nameorg.cometd levelWARN /logger namech.qos.logback levelWARN /logger namecom.springapp.mvc levelDEBUG /logger namecom.qf.mapper levelDEBUG/logger!– logger namecom.ibatis levelDEBUG/logger –root levelERRORappender-ref refstdout /appender-ref reflogfile //root
/configuration配置到 web.xml 中!– logback –context-paramparam-namelogbackConfigLocation/param-nameparam-valueclasspath:logback.xml/param-value/context-paramlistenerlistener-classch.qos.logback.ext.spring.web.LogbackConfigListener/listener-class/listener整合 servlet 后期 换成 springmvc ,当前先用servlet
1.添加依赖 !–整合一下 web–dependencygroupIdorg.springframework/groupIdartifactIdspring-web/artifactIdversion5.2.0.RELEASE/version/dependencydependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependencydependencygroupIdjavax.servlet/groupIdartifactIdjsp-api/artifactIdversion2.0/versionscopeprovided/scope/dependencydependencygroupIdjavax.servlet/groupIdartifactIdjstl/artifactIdversion1.2/version/dependency2.在web.xml 中 添加一个监听器 用于读取spring 的配置文件 创建 容器 context-paramparam-namecontextConfigLocation/param-nameparam-valueclasspath:applicationContext.xml/param-value/context-param!–这个监听器 帮助加载spring 配置文件创建spring 容器–listenerlistener-classorg.springframework.web.context.ContextLoaderListener/listener-class/listener创建servlet 在 servlet中 得到 容器对象 再通过容器对象来得到 service bean
package com.qf.web;import com.qf.pojo.User;
import com.qf.service.UserService;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** ClassName : LoginServlet* Author : glls* Date: 2021/8/10 14:43* Description :*/
WebServlet(/login)
public class LoginServlet extends HttpServlet {private UserService userService;Overridepublic void init() throws ServletException {WebApplicationContext applicationContext WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());userService applicationContext.getBean(userService, UserService.class);}Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {this.doPost(req,resp);}Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String username req.getParameter(username);String password req.getParameter(password);//有了spring 管理 bean ,就不要再自己new 对象了 所以//从容器 把 userService 取出来User user new User();user.setName(username);user.setPassword(password);User result userService.login(user);System.out.println(result);}
}
十六、事务【重点】 什么是事务 事务是数据库操作的基本单元逻辑上的一组操作要么都成功要么都失败也就是说只有一组操作中 有一个失败了那么这组操作都失败 举个栗子 wsc转账500给wjl update t_account set money money-500 where accountid 1 wsc 的账户 减500 update t_account set money money500 where accountid2 wjl的账户 加 500 事务的特性 ACID A atomicity 原子性 一组操作 整体不可拆分要么都成功 要么都失败 C consistency 一致性 数据在事务的前后业务整体一致 I isolation 隔离性 事务之间 互相隔离 D durability 持久性 一旦事务执行成功 数据一定会落盘在数据库
3.准备事务的环境
账户表 service 定义转账方法 //转账操作Overridepublic void transferMoney(int from, int to, double money) {//from 给 to 转了 money//一个账户 扣钱accountMapper.reduceMoney(from,money);//模拟一个异常int i 5⁄0;//一个账户加钱accountMapper.addMOney(to,money);}dao Update(update t_account set money money - #{money} where userid #{from} )void reduceMoney(Param(from) int from,Param(money) double money);Update(update t_account set money money #{money} where userid #{to} )void addMOney(Param(to)int to, Param(money) double money);
转账过程中 模拟异常出现一个账户扣钱了另一个账户却没有加钱 数据不一致问题 怎么解决
使用事务 进行解决
spring提供了 事务的解决方案 底层原理是 AOP
基于注解的方案 掌握基于xml配置文件的方式 了解 16.1 配置DataSourceTransactionManager 事务管理器其中持有DataSource可以控制事务功能commit,rollback等。 !– 1. 引入一个事务管理器其中依赖DataSource,借以获得连接进而控制事务逻辑 –
bean idtx classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property
/bean注意DataSourceTransactionManager 和 SqlSessionFactoryBean 要注入同一个DataSource的Bean否则事务控制失败!!! ####16.2 配置事务通知 基于事务管理器进一步定制生成一个额外功能Advice。 此Advice可以切入任何需要事务的方法通过事务管理器为方法控制事务。 tx:advice idtxManager transaction-managertxtx:attributes!–tx:method nameinsertUser rollback-forException isolationDEFAULT propagationREQUIRED read-onlyfalse/–!– 以User结尾的方法切入此方法时采用对应事务实行–tx:method nameUser rollback-forException/!– 以query开头的方法切入此方法时采用对应事务实行 –tx:method namequery propagationSUPPORTS/!– 剩余所有方法 –tx:method name//tx:attributes
/tx:advice16.3 事务属性
16.3.1 隔离级别
16.3.1.1 概念 isolation 隔离级别 名称描述default(默认值采用数据库的默认的设置) 建议read-uncommited读未提交read-commited读提交 Oracle数据库默认的隔离级别repeatable-read可重复读 MySQL数据库默认的隔离级别serialized-read序列化读 隔离级别由低到高为read-uncommited read-commited repeatable-read serialized-read 16.3.1.2 特性 安全性级别越高多事务并发时越安全。因为共享的数据越来越少事务间彼此干扰减少。 并发性级别越高多事务并发时并发越差。因为共享的数据越来越少事务间阻塞情况增多。 16.3.1.3 并发问题 事务并发时的安全问题 问题描述脏读一个事务读取到另一个事务还未提交的数据。大于等于 read-commited 可防止不可重复读一个事务内多次读取一行数据的相同内容其结果不一致。大于等于 repeatable-read 可防止幻影读幻读并不是说两次读取获取的结果集不同幻读侧重的方面是某一次的 select 操作得到的结果所表征的数据状态无法支撑后续的业务操作。更为具体一些select 某记录是否存在不存在准备插入此记录但执行 insert 时发现此记录已存在无法插入此时就发生了幻读。mysql 幻读的详解、实例及解决办法 - SegmentFault 思否
16.3.2 传播行为 propagation传播行为 当涉及到事务嵌套Service调用Service时可以设置 SUPPORTS 不存在外部事务则不开启新事务存在外部事务则合并到外部事务中。适合查询 REQUIRED 不存在外部事务则开启新事务存在外部事务则合并到外部事务中。 (默认值)适合增删改 参考资料 事务隔离级别和传播行为_Spring事务的传播行为和隔离级别_weixin_39604685的博客-CSDN博客
16.3.3 读写性 readonly 读写性 true只读可提高查询效率。(适合查询) false可读可写。 (默认值)适合增删改 16.3.4 事务超时 timeout事务超时时间 当前事务所需操作的数据被其他事务占用则等待。 100自定义等待时间100秒。-1由数据库指定等待时间默认值。建议 16.3.5 事务回滚 rollback-for 回滚属性 如果事务中抛出 RuntimeException,则自动回滚 如果事务中抛出 CheckException(非运行时异常 Exception)不会自动回滚而是默认提交事务 处理方案 : 将CheckException转换成RuntimException上抛或 设置 rollback-for“Exception.class” 16.4 编织 将事务管理的Advice 切入需要事务的业务方法中 aop:configaop:pointcut expressionexecution( com.qf.spring.service.UserServiceImpl.(..)) idpc/!– 组织切面 –aop:advisor advice-reftxManager pointcut-refpc/
/aop:config基于xml的步骤
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxmlns:contexthttp://www.springframework.org/schema/contextxmlns:txhttp://www.springframework.org/schema/txxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd!–1. 配置事务管理器–bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property/bean!–2. 配置 事务的通知–tx:advice idtxadvice transaction-managertransactionManagertx:attributestx:method nametransferMoney propagationREQUIRED//tx:attributes/tx:advice!–3.织入切面–aop:config!–配置切点–aop:pointcut idtxpoint expressionexecution( com.qf.service.impl.AccountServiceImpl.*(..))/!–配置切面–aop:advisor advice-reftxadvice pointcut-reftxpoint/aop:advisor/aop:config/beans 十七、注解开发
1.什么是注解
1注解是代码特殊标记格式注解名称(属性名称属性值, 属性名称属性值…)
2使用注解注解作用在类上面方法上面属性上面
3使用注解目的简化 xml 配置
2.spring针对Bean管理创建对象提供的注解
1Component
2Service
3Controller
4Repository
上面四个注解功能是一样的都可以用来创建 bean 实例
3.基于注解方式 实现对象创建
1.需要aop 依赖的支持 spring-aop
2.开启组件扫描
1 如果扫描多个包多个包使用逗号隔开 2 扫描包上层目录?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxmlns:phttp://www.springframework.org/schema/pxmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd!– 扫描–context:component-scan base-packagecom.glls/context:component-scan/beans3.创建类 在类上添加创建bean 的注解
//在注解里面 value 属性值可以省略不写
//默认值是类名称首字母小写
//UserService – userService
4.开启组件扫描细节配置 !–下面的配置 是 只扫描Controllercontext:component-scan base-packagecom.glls use-default-filtersfalsecontext:include-filter typeannotation expressionorg.springframework.stereotype.Controller//context:component-scan–!–下面的配置 是 忽略Controllercontext:component-scan base-packagecom.glls context:exclude-filter typeannotation expressionorg.springframework.stereotype.Controller//context:component-scan–!–扫描该包下 的所有注解–context:component-scan base-packagecom.glls /context:component-scan5.基于注解的方式 实现属性注入
1Autowired先根据类型注入 再根据名字注入
第一步 把 service 和 dao 对象创建在 service 和 dao 类添加创建对象注解
第二步 在 service 注入 dao 对象在 service 类添加 dao 类型属性在属性上面使用注解
Service public class UserService { //定义 dao 类型属性 //不需要添加 set 方法 //添加注入属性注解 Autowired private UserDao userDao; public void add() { System.out.println(service add…….); userDao.add(); } }2Qualifier根据名称进行注入
这个Qualifier 注解的使用和上面Autowired 一起使用
//定义 dao 类型属性 //不需要添加 set 方法//添加注入属性注解 Autowired //根据类型进行注入 Qualifier(value userDaoImpl1) //根据名称进行注入 private UserDao userDao;3Resource先根据名字注入 再根据类型注入
//Resource //根据类型进行注入 Resource(name userDaoImpl1) //根据名称进行注入 private UserDao userDao; 4Value注入普通类型属性
Value(value abc) private String name;6、完全注解开发
1创建配置类替代 xml 配置文件
Configuration //作为配置类替代 xml 配置文件 ComponentScan(basePackages {com.glls}) public class SpringConfig { } 2编写测试类
Test public void testService2() { //加载配置类 ApplicationContext context new AnnotationConfigApplicationContext(SpringConfig.class); UserService userService context.getBean(userService, UserService.class); System.out.println(userService); userService.add(); }[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2kf3XTow-1682258194561)(D:\前锋学习笔记\笔记\image-20230423162534899.png)] 17.1 声明bean 用于替换自建类型组件的 bean…标签可以更快速的声明bean Service 业务类专用 Repository dao实现类专用 Controller web层专用 Component 通用 Scope 用户控制bean的创建模式 // Service说明 此类是一个业务类需要将此类纳入工厂 等价替换掉 bean classxxx.UserServiceImpl
// Service默认beanId 首字母小写的类名userServiceImpl
// Service(userService) 自定义beanId为userService
Service //声明bean且iduserServiceImpl
Scope(singleton) //声明创建模式默认为单例模式 Scope(prototype)即可设置为多例模式
public class UserServiceImpl implements UserService {…
}17.2 注入(DI) 用于完成bean中属性值的注入 Autowired 基于类型自动注入 先根据类型注入 如果找到多个 再根据名称注入Resource 基于名称自动注入 先根据名称注入 如果根据名称没找到 则根据类型找 根据类型 找到多个 则报错 找到一个则注入Qualifier(“userDAO”) 限定要自动注入的bean的id一般和Autowired联用Value 注入简单类型数据 (jdk8种String) Service
public class UserServiceImpl implements UserService {Autowired //注入类型为UserDAO的beanQualifier(userDAO2) //如果有多个类型为UserDAO的bean可以用此注解从中挑选一个private UserDAO userDAO;
}Service
public class UserServiceImpl implements UserService {Resource(userDAO3) //注入id“userDAO3”的beanprivate UserDAO userDAO;/Resource //注入id“userDAO”的beanprivate UserDAO userDAO;/
}public class XX{Value(100) //注入数字private Integer id;Value(shine) //注入Stringprivate String name;
}17.3 事务控制 用于控制事务切入 Transactional 工厂配置中的 tx:advice… 和 aop:config… 可以省略 !! //类中的每个方法都切入事务(有自己的事务控制的方法除外)
Transactional(isolationIsolation.READ_COMMITTED,propagationPropagation.REQUIRED,readOnlyfalse,rollbackForException.class,timeout -1)
public class UserServiceImpl implements UserService {…//该方法自己的事务控制仅对此方法有效Transactional(propagationPropagation.SUPPORTS)public ListUser queryAll() {return userDao.queryAll();}public void save(User user){userDao.save(user);}
}17.4 注解所需配置
!– 告知spring哪些包中 有被注解的类、方法、属性 –
!– context:component-scan base-packagecom.qf.a,com.xx.b/context:component-scan –
context:component-scan base-packagecom.qf/context:component-scan!– 1. 引入一个事务管理器其中依赖DataSource,借以获得连接进而控制事务逻辑 –bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManagerproperty namedataSource refdataSource/property/bean!– 开启事务的注解–tx:annotation-driven transaction-managertransactionManager/17.5 AOP开发
17.5.1 注解使用
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;Aspect // 声明此类是一个切面类会包含切入点(pointcut)和通知(advice)
Component //声明组件进入工厂
public class MyAspect {// 定义切入点Pointcut(execution(* com.qf.spring.service.UserServiceImpl.*(..)))public void pc(){}Before(pc()) // 前置通知public void mybefore(JoinPoint a) {System.out.println(target:a.getTarget());System.out.println(args:a.getArgs());System.out.println(methods name:a.getSignature().getName());System.out.println(before~~);}AfterReturning(valuepc(),returningret) // 后置通知public void myAfterReturning(JoinPoint a,Object ret){System.out.println(after:ret);}Around(pc()) // 环绕通知public Object myInterceptor(ProceedingJoinPoint p) throws Throwable {System.out.println(interceptor1);Object ret p.proceed();System.out.println(interceptor2~~);return ret;}AfterThrowing(valuepc(),throwingex) // 异常通知public void myThrows(JoinPoint jp,Exception ex){System.out.println(throws);System.out.println(ex.getMessage());}
}17.5.2 配置
!– 添加如下配置,启用aop注解 –
aop:aspectj-autoproxy/aop:aspectj-autoproxy十八、集成JUnit 18.1 导入依赖
dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion4.3.6.RELEASE/version
/dependency
dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.12/version
/dependency18.2 编码 可以免去工厂的创建过程 可以直接将要测试的组件注入到测试类。 RunWith(SpringJUnit4ClassRunner.class) //由SpringJUnit4ClassRunner启动测试
ContextConfiguration(classpath:applicationContext.xml) //spring的配置文件位置
public class SpringTest{//当前测试类也会被纳入工厂中所以其中属性可以注入Autowired // 注入要测试的组件Qualifier(userDAO)private UserDAO userDAO;Testpublic void test(){// 测试使用userDAOuserDAO.queryUser();….}
}集成Junit 5 !–spring整合 junit 5 –dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion5.2.9.RELEASE/version/dependencydependencygroupIdorg.junit.jupiter/groupIdartifactIdjunit-jupiter-api/artifactIdversion5.5.2/versionscopetest/scope/dependency测试类
SpringJUnitConfig(locations classpath:applicationContext2.xml)
class OrderServiceImplTest {Autowiredprivate OrderService orderService;Testvoid findOrderByUserId() {ListOrder orderByUserId orderService.findOrderByUserId(10);}
}十九、个人扩展
spring5 新的模块 webflux
1、SpringWebflux 介绍
1是 Spring5 添加新的模块用于 web 开发的功能和 SpringMVC 类似的Webflux 使用 当前一种比较流程响应式编程出现的框架。 2使用传统 web 框架比如 SpringMVC这些基于 Servlet 容器Webflux 是一种异步非阻 塞的框架异步非阻塞的框架在 Servlet3.1 以后才支持核心是基于 Reactor 的相关 API 实现 的。
3解释什么是异步非阻塞
异步和同步非阻塞和阻塞上面都是针对对象不一样异步和同步针对调用者调用者发送请求如果等着对方回应之后才去做其他事情就是同 步如果发送请求之后不等着对方回应就去做其他事情就是异步阻塞和非阻塞针对被调用者被调用者受到请求之后做完请求任务之后才给出反馈就是阻 塞受到请求之后马上给出反馈然后再去做事情就是非阻塞
4Webflux 特点
第一 非阻塞式在有限资源下提高系统吞吐量和伸缩性以 Reactor 为基础实现响应式编程
第二 函数式编程Spring5 框架基于 java8Webflux 使用 Java8 函数式编程方式实现路由请求
5比较 SpringMVC 第一 两个框架都可以使用注解方式都运行在 Tomet 等容器中
第二 SpringMVC 采用命令式编程Webflux 采用异步响应式编程
2、响应式编程Java 实现
1什么是响应式编程 响应式编程是一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便 地表达静态或动态的数据流而相关的计算模型会自动将变化的值通过数据流进行传播。 电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似B1C1的公 式而包含公式的单元格的值会依据其他单元格的值的变化而变化。
3.手写spring 伪源码
创建maven工程 无需添加任何依赖 在spring包下创建容器类 GllsApplicationContext 二十 个人源码解析
个人学习
源码分析 ClassPathXmlApplicationContext superparent; 此时 传进来的super 为空 在这个方法中 调父类AbstractApplicationContext 构造方法 创建了资源解析器 /** Create a new AbstractApplicationContext with no parent. */ public AbstractApplicationContext() { this.resourcePatternResolver getResourcePatternResolver(); } setConfigLocations(configLocations); 调父类构造 这个方法由子类重写 总结 resolvePath(String path) 方法做了什么事情
1.实例化 Environment
2.解析传进来的 path refresh方法
AbstractApplicationContext 类中Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn(Exception encountered during context initialization - cancelling refresh attempt: ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset active flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Springs core, since we// might not ever need metadata for singleton beans anymore…resetCommonCaches();}}}
- 上一篇: 外贸网站建设报价表旅游公司网站开发
- 下一篇: 外贸网站建设的意义怎么制作网站主页
相关文章
-
外贸网站建设报价表旅游公司网站开发
外贸网站建设报价表旅游公司网站开发
- 技术栈
- 2026年04月20日
-
外贸网站海外推广西安附近网络营销运营公司
外贸网站海外推广西安附近网络营销运营公司
- 技术栈
- 2026年04月20日
-
外贸网站翻墙做广告全国工商企业查询
外贸网站翻墙做广告全国工商企业查询
- 技术栈
- 2026年04月20日
-
外贸网站建设的意义怎么制作网站主页
外贸网站建设的意义怎么制作网站主页
- 技术栈
- 2026年04月20日
-
外贸网站建设公司青岛阿里云个人域名备案流程
外贸网站建设公司青岛阿里云个人域名备案流程
- 技术栈
- 2026年04月20日
-
外贸网站建设哪家合适wordpress的文件
外贸网站建设哪家合适wordpress的文件
- 技术栈
- 2026年04月20日
