灵谷百科

入门级-SSM框架(Spring篇)

灵谷百科
Spring IOC(控制反正)和DI(依赖注入)是什么? IOC (Inverse of Control)控制反转: 曾经: 静态依赖:类中的依赖的对象是通过New关键字在堆中创建对象并被引用进行依赖对象调用方法 动态依赖:通过反射,获取依赖对象类的Class对象,创建实例并依赖对象实例调用方法现在: 将依赖的对象交给Spring IOC容器中统一管理,需要依赖某个对象时通过IOC容器依赖注入到对应的类中 ,那么这么一来依赖的对象控制权在第三方的手中。可能是xml配置文件、可能是JavaBean注解开发 DI (Dependency Injection) 依赖注入: 基于控制反转思想进行实现,对底层原生代码进行封装提供了对应的API,将需要依赖的对象剥离到Spring IOC容器中管理的类通过Spring API进行注入到需要依赖的位置 IOC和DI的关系 IOC控制反转的抽象思想将对象进行管理,DI是注入的具体实现行为。IOC和DI互相搭档,实现了降低解耦。 DI让对象和对象依赖的功能实现,而对象在IOC中进行统一管理,所以依赖的功能需要基于IOC容器为DI提供数据Bean对象 曾经: 多态关系进行赋值依赖,类中维护对象之间的依赖关系。若发生变动,当需要修改依赖子为实现B时,需要修改代码,重构系统应用 现在: 通过resource外部文件IOC容器维护类依赖关系。若依赖关系发生变动,无需修改java代码,仅修resource配置文件 使用前不得不知道的知识点? 如何从java目录中读取resource目录中的IOC容器? Bean的作用范围(既多次获取是否是同一个地址值对象) [默认模式:单例模式] [其他模式:原型模式] 每次获取都创建新的地址值对象 生命周期方法如何触发执行任务?(销毁方法触发需要执行特定的方法,否则无法执行) 自己配置触发执行 public class BookDaoImpl implements BookDao {public void save() {System.out.println("book dao save ...");}public void init(){System.out.println("init...");}public void destory(){System.out.println("destory...");} } 通过实现规范触发执行 public class Main implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("service init");}@Overridepublic void destroy() throws Exception {System.out.println("service destroy");} } [实现规范] 即可简单配置 解决销毁方法无法执行的问题,原因是因为JVM退出后,IOC容器没有来得及关闭 手工关闭容器 ConfigurableApplicationContext接口close()操作注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机 ConfigurableApplicationContext接口registerShutdownHook()操作 Spring实例化和依赖注入的方式分别有什么? Spring实现实例化的四种方式(即管理对象,仅创建对象,并不初始化成员变量) 构造器实例化Bean : 使用无参或无参 [无参实例化] [有参实例化] 需要额外加入构造依赖注入:分为www.ccchp.com形参名匹配 2.type类型匹配 3.index索引匹配(0开始) 注解型 类@Component @Controller @Service @Reposity 范围@Scope(“singleton”) 静态工厂方式实例化Bean: [静态工厂]随着类的加载而加载,即类名可以直接调用静态方法。无需对工厂产品进行注册Bean 注解型 方法返回值@Bean 实例工厂方法实例化Bean: [实例工厂]顾名思义,需要实例化获取工厂对象,才能调用getter方法获取产品,分两步。无需对工厂产品注册Bean 注解型 方法返回值@Bean 通用Spring工厂实例化Bean: [步骤一 java目录:继承springFrameWork的工厂规范接口] class UserInstanceFactory implements FactoryBean [步骤二 resource目录:Spring规范通用工厂] 依赖注入的四种方式(即实例化对象,又成员初始化赋值) 构造方法注入使用此方式需要注入形参所有的属性 [有参构造器注入] 无参构造器注入个辣子🌶️,无需考虑- 形参名 匹配注入 - 形参类型 匹配注入 - 形参索引 匹配注入 Setter方法注入 (设值注入) 可选的依赖关系,但需要提供无参构造或者无参的静态工厂方法创建对象集合数组Proerties注入仅与构造constructor-arg不同,可以传入多个相同集合不同属性名,推荐使用Setter方式注入,因为灵活 [Setter方法注入] 灵活优于构造器注入,可以对部分成员不进行初始化 100200300 itcastitheimaboxueguchuanzhihuiitcastitheimaboxueguchinahenankaifeng 自动装配注入基于Setter方法 [自动装配注入] 自动从IOC容器中匹配其他Bean进行填充 - 类型自动注入:务必保证IOC中Bean的Type唯一性 - 属性名自动注入: 务必保证IOC中Bean的id名符合Setter后属性名 注解注入 @Autowired :按照类型注入 [ 组合@Qualifier 按照名称装配 ] 、 @Value: 普通类型注入 或 读取properties 配置文件 “${}” 无需Setter 、 @Resource : 指定名称name和类型type会进行唯一匹配,找不到则抛出异常 指定仅名称name,按照名称(id)匹配Bean进行装配,找不到抛出异常 指定名称type,按照类型匹配Bean进行装配,找不到抛出异常 不进行任何指定,自动按照优先byName方式进行匹配,无法匹配尝试进行type匹配 容器类 配置@Coinfiguration + 扫描目录下Bean @Component(多目录1,多目录2) + @Import(获取子容器1,获取子容器2) 属性配置读取 @PropertySource(“classpath:jdbc.properties”) 测试类(pom依赖容易发生不兼容问题) spring测试启动器 @RunWith(SpringJUnit4ClassRunner.class) 获取java容器 @ContextConfiguration(classes = {SpringConfiguration.class}) Data Access/Integration (数据 访问/一体化) (简化与第三方框架整合) 【1.Dependency依赖准备】 88org.springframeworkspring-context5.2.10.RELEASEorg.mybatismybatis3.5.6org.mybatismybatis-spring1.3.0mysqlmysql-connector-java8.0.25com.alibabadruid1.1.16c3p0c3p00.9.1.2org.springframeworkspring-jdbc5.2.10.RELEASEjunitjunit4.12testorg.springframeworkspring-test5.2.10.RELEASEorg.aspectjaspectjweaver1.9.7 【2.配置Bean】 【解决应配置问题】(多属性配置文件可合并) 【3.创建容器】 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); ApplicationContext ctx = new ClassPathXmlApplicationContext("context_1.xml", "context_2.xml"); ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\applicationContext.xml"); Resource resources = new ClassPathResource("applicationContext.xml"); BeanFactory bf = new XmlBeanFactory(resources); ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); Spring AOP(面向切面编程)(非入侵式,不需要修改原处代码即可对功能增强) 切面织入依赖 org.aspectjaspectjweaver1.9.7 核心概念 连接点(JoinPoint) 被增强的方法 切入点(Pointcut) 增强的代理方法 通知(Advice) 对增强方法的执行时机 通知类 定义多个通知时机 切面(Aspect) 执行的过程 或 是对应关系 通知类 @Aspect 标记为切面类 容器类 @EnableAspectJAutoProxy 配置开启 切入点 @PointCut(execution(public * com.itheima..UserService.find())) 任意单词* execution(public * com.itheima..UserService.find*(*)) 多级路径.. executio\n(public User com…UserService.findById(…)) 子级匹配+ execution(* *…Service+.(…)) 为什么使用AOP? 降低耦合度侵略性小,避免了修改代码复用性高,制定增强的代码对切入点进行注入 AOP如何使用?用到了什么地方? 前置通知:@Before 后置通知:@After 返回后通知:@AfterReturning 类似于finlly 异常通知:@AfterThrowing 仅发生异常 环绕通知:@Around 前置+后置混合+异常捕捉+返回后通知 日志处理(执行次数追踪,性能监测,异常记录) 事务处理(对增删改这类操作进行事务管理) 事务管理 配置类开启事务管理 @EnableTransactionManagement 事务传播级别(业务处理层) @Transactional(propagation = Propagation.REQUIRES_NEW,readOnly=true) 什么是动态代理?动态代理都有哪些? 不修改代码的情况下,对代码进行增强,使用时字节码随用随创建,随用随加载 基于接口的动态代理,要求:被代理类最少实现一个接口 提供者:JDK官方,涉及类:Proxy 创建代理对象方法:newProxyInstance 涉及到创建对象方法里的参数:ClassLoader:类加载器【固定写法】 负责加载代理对象使用的字节码,需要和被代理对象使用相同类加载器: Class[]:字节码数组【固定写法】 负责让生成的代理对象具有和被代理对象相同的方法。 写什么要看被代理对象是一个接口还是一个实现类 如果是一个接口:new Class[]{接口} 如果是一个实现类:XXX.getClass().getInterfaces() InvocationHandler:一个接口,需要我们提高该接口的实现,写的是一个接口的实现类 增强代码,谁用写谁,通常是匿名内部类,不是绝对的 基于子类的动态代理,要求:需要导入第三方cglib的坐标依赖。 提供者:Cglib第三方,涉及类:Enhancer 创建代理对象的方法:create 方法的参数: Class: 字节码对象,用于加载代理对象字节码,写的是被代理对象的字节码 Callback:如何代理。提供增强代码。 (它是个接口,需要实现这个接口没有的方法,需要使用它的子接口 MethodInterceptor) 动态代理使用场景 基于AOP思想的方法增强自动以连接池中,实现Connection的cloase方法将连接还回池中的操作,可以使用动态代理或装饰者模式解决全站中文乱码,get和post两种提交方式 在get方式需要对一下三个方法增强,用于解决乱码 (tomcat8.5底层解决) String value= getParameter(String name); String[]value=getParameterValues(String name); Mapmap = getParameterMa(); 什么是静态代理? JDK动态代理 与 CGLIB动态代理的区别? 相同点: 均属于Spring AOP技术动态代理的实现方式 不同点: jdk动态代理:通过反射接收被代理的类,核心InvocationHandler和Proxy类 缺点:被代理类必须实现接口,也就是说被代理的类必须有接口的实现关系 cglib动态代理:适用于没有实现接口的类,cglib是一个代码生成类库,运行阶段动态生成某个类的子类(目标类),cglib通过继承的方式动态代理 缺点:类将需要能够被继承,不能被标记为final,那么无法cglib动态代理 singleton(默认:单例模式)IOC仅创建一个Bean实例,每次返回同一个实例 生命周期与容器同长prorotype(原型[多例]模式)IOC创建多个实例,每次返回一个新的实例 生命周期使用完被垃圾回收request(Http请求)每次HTTP请求都会创建一个新的Bean,使用WebApplicatonContextsession(当前会话)一个Session共享一个Bean,不同Session使用不同的实例 不考虑事务隔离性引发的安全问题? 脏读: 读取到其他事务未提交回滚的数据不可重复读: 事务需要重复读一些数据,但没有执行完时,读取到其他事务操作后的数据,导致重复读取的数据不一致幻读: 事务执行时,其他事务执行修改的数据符合当前逻辑,导致当前事务查询多次结果不一致 事务的隔离界别 read uncommited读未提交: 三种安全问题都会发生read commited只读已提交: 重复读 幻读repeatable read可重读读: 幻读serializable串行化: 三种安全问题都被解决 隔离界级别越高,安全性高,效率越低 Spring如何管理事务? 编程式事务管理: Spring推荐使用TransactionTemplate工具类(但是开发中声明式事务使用较多) 缺点: 1.事务管理的代码和业务代码将会同时出现,分层不明确 2.使用工具类进行类与类的依赖,耦合性强声明式事务管理: 利用AOP面向切面编程思想,选择目标,对目标进行环绕时拦截。在方法目标执行前加入或创建一个事务,在方法执行后,根据情况选择提交或是回滚事务. 优点: 业务代码与事务分离,事务部分统一在Spring的xml配置文件中集中管理降低耦合性 Spring的事务管理器有什么? Spring不会直接管理事务,对其他多平台提供的事务管理器接口,事务管理器充当一个工具类,从而用户在Spring使用事务,不要用关心事务的实现 Spring的事务只读是强制的吗? 选择只读Spring将会对查询的方法进行性能优化 对于事务需要设置多长超时时间? 事务的执行时间不能过长,如果超时需要记录保存日志 项目中如何实现使用Spring事务? Spring提供三个接口,事务需要这三个的实现共同执行 PlatFormTransactionManager commit 事务提交 rollback 事务回滚 getTransaction 获取事务TRansactonDefinition getIsonlationLevel:获取隔离级别 getPropagetionBehavior:获取传播行为 getTimeout获取超时时间 isReadOnly是否只读(false可读写,true只读)TransactionStatus hasSavepoint返回事务内部是否包含一个保存点 isComplated返回事务是否已经完成提交或回滚 isNewTransaction判断是否是一个新事物 工厂模式BeanFactory以及ApplciationContext模板模式BeanFactory以及ApplciationContext代理模式AOP的JDK动态代理单例模式创建Bean的时候策略模式JdbcTmplate通过SQL获取数据,但获取数据的分组类型 RowMapper接口以及BeanPropertyRowMapper的是实现类 RowMapper接口定义规范,而实现类提供不同的策略观察者模式 WebApplciatonContext,是通过ContextLoaderListener监听器实现创建的.监听器就是观察者模式的具体实现 (事件源 时间 监听者)适配器模式 @Controller注解 实现Controller接口 实现HttpRequestHandler接口 8.装饰者模式

发表评论 (已有0条评论)

还木有评论哦,快来抢沙发吧~