复习宝典之Spring
查看更多宝典,请点击《金三银四,你的专属面试宝典》
第六章:Spring
Spring容器是Spring的核心,一切Spring bean都存储在Spring容器内,并由其通过IoC技术管理。Spring容器也就是一个bean工厂(BeanFactory)。应用中bean的实例化,获取,销毁等都是由这个bean工厂管理的。
org.springframework.context.ApplicationContext接口用于完成容器的配置,初始化,管理bean。一个Spring容器就是某个实现了ApplicationContext接口的类的实例。也就是说,从代码层面,Spring容器其实就是一个ApplicationContext。
在普通的JAVA工程中,我们可以通过代码显式new一个ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext来初始化一个Spring容器。
在Web工程中,我们一般是通过配置web.xml的方式来初始化Spring容器。
1)框架特征
轻量--从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。
控制反转--Spring通过一种称作控制反转(IoC)的技术促进了低耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反--不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。
面向切面--Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的--完成业务逻辑--仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。
容器--Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建--基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例--以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。
框架--Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。
MVC--Spring的作用是整合,但不仅仅限于整合,Spring 框架可以被看做是一个企业解决方案级别的框架。客户端发送请求,服务器控制器(由DispatcherServlet实现的)完成请求的转发,控制器调用一个用于映射的类HandlerMapping,该类用于将请求映射到对应的处理器来处理请求。HandlerMapping 将请求映射到对应的处理器Controller(相当于Action)在Spring 当中如果写一些处理器组件,一般实现Controller 接口,在Controller 中就可以调用一些Service 或DAO 来进行数据操作 ModelAndView 用于存放从DAO 中取出的数据,还可以存放响应视图的一些数据。 如果想将处理结果返回给用户,那么在Spring 框架中还提供一个视图组件ViewResolver,该组件根据Controller 返回的标示,找到对应的视图,将响应response 返回给用户。
所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。
2)不仅仅是容器
spring容器工厂:spring对所有对象都可以进行管理,然后通过单例模式创建一个全局唯一的一个实例对象,通过工厂模式在调用注入的接口时实例化对象。
Spring模式包含:单例模式和工厂模式
单例模式:
a.单例模式限制了类实例的创建,但采用这种模式设计的类,可以保证仅有一个实例,并可提供访问该实例的全局访问点。
b.J2EE应用的大量组件,都需要保证一个类只有一个实例,比如数据库引擎访问只有一个。
c.但是更多时候,为了提高性能,程序应尽量减少Java 对象的创建和销毁时的开销。使用单例模式可避免Java 类被多次实例化。
d. 为了防止单态模式的类被多次实例化,应将类的构造器设成私有,这样就保证了只能通过静态方法获得类实例。
工厂模式:
a.工厂模式是根据调用数据返回某个类的一个实例,此类可以是多个类的某一个类。
b.通常,这些类满足共同的规则(接口)或父类。调用者只关心工厂生产的实例是否满足某种规范,即实现的某个接口是否可供自己正常调用(调用者仅仅使用)。
c.该模式给对象之间作出了清晰的角色划分,降低程序的耦合。
d.接口产生的全部实例通常用于实现相同接口,接口里定义了全部实例共同拥有的方法,这些方法在不同的实现类中实现的方式不同。
f.从而使程序调用者无须关心方法的具体实现,降低了系统异构的代价。
3)IOC(控制反转)与 DI(依赖注入)
IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
IoC很好的体现了面向对象设计法则之一,好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
IoC(Inversion of Control,控制反转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。
Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
DI(Dependency Injection),即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。
4)AOP(面向切面编程)
AOP编程思想:横向重复代码,纵向抽取;就是说多个地方重复的代码可以抽取出来公用(过滤器等可以体现)
动态代理:动态代理可以体现AOP思想;对目标方法进行增强
SpringAOP开发:封装了动态代理代码(包括cglib代理),可以对任何类进行代理增强
AOP(Aspect Orient Programming),作为面向对象编程的一种补充,广泛应用于处理一些具有横切性质的系统级服务,如事务管理、安全检查、缓存、对象池管理等。AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类,其中静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。
Spring 的 AOP 代理由 Spring 的 IoC 容器负责生成、管理,其依赖关系也由 IoC 容器负责管理。因此,AOP 代理可以直接使用容器中的其他 Bean 实例作为目标,这种关系可由 IoC 容器的依赖注入提供。
纵观 AOP 编程,其中需要程序员参与的只有 3 个部分:
定义普通业务组件。
定义切入点,一个切入点可能横切多个业务组件。
定义增强处理,增强处理就是在 AOP 框架为普通业务组件织入的处理动作。
上面 3 个部分的第一个部分是最平常不过的事情,无须额外说明。那么进行 AOP 编程的关键就是定义切入点和定义增强处理。一旦定义了合适的切入点和增强处理,AOP 框架将会自动生成 AOP 代理
5)spring基础知识
spring的一些基本概念:
<?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"> <!-- spring:管理对象的容器 -->
<!-- spring IOC:控制反转,通过spring创建对象(无需手动创建) -->
<!-- DI:依赖注入;就是给对象的某些属性赋值 --> <!-- 将User对象交给spring管理 -->
<!-- bean元素:描述需要spring管理的对象;name属性:给对象取个别名,获取对象时需要;
class属性:被管理对象的完整类名;id属性:与name属性一模一样,不可重复,不能使用特殊字符(因此要name)-->
<!-- 创建方式一:spring调用无参构造创建对象 -->
<!-- scope:singleton:表示单例对象,在spring容器中只会存在一个实例 -->
<!-- scope:prototype:表示多例对象,每次获取都会创建一个新的对象;整合struts2时必须为多例 -->
<!-- 生命周期方法配置init,destroy -->
<bean name="user" class="com.bean.User" scope="singleton" init-method="init" destroy-method="destroy"></bean> <!-- 创建方式二:通过静态工厂的某个方法创建一个user对象 -->
<bean name="user1" class="com.bean.UserFactory" factory-method="createUser"></bean> <!-- 创建方式三:实例工厂创建对象 -->
<bean name="user2" factory-bean="userFactory" factory-method="createUser2"></bean>
<bean name="userFactory" class="com.bean.UserFactory"></bean> <!-- 模块化配置,可以导入其他spring配置文件 -->
<!--<import resource="applicationContext.xml"/>-->
</beans>
spring依赖注入方式:
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- set方式注入 -->
<bean name="user" class="com.bean.User">
<!-- 值类型注入 -->
<property name="name" value="xdzy"/>
<property name="age" value="18"/>
<!-- 引用类型注入 -->
<property name="car" ref="car"/>
</bean> <!-- 将car对象配置到spring容器 -->
<bean name="car" class="com.bean.Car">
<property name="name" value="兰博基尼"/>
<property name="color" value="红色"/>
</bean> <!-- 构造函数注入 -->
<bean name="user1" class="com.bean.User">
<!-- 当构造方法参数位置不同,可以通过index确定参数位置 -->
<!-- 当构造方法参数类型不同,可以通过type确定参数类型 -->
<constructor-arg name="name" value="xdzy" index="0" type="java.lang.String"/>
<constructor-arg name="car" ref="car"/>
</bean> <!-- p属性注入 -->
<!-- 需加入xmlns:p="http://www.springframework.org/schema/p" -->
<bean name="user2" class="com.bean.User" p:name="xdzy" p:age="18" p:car-ref="car"/> <!-- spel表达式注入;可以实现动态注入 -->
<bean name="user3" class="com.bean.User">
<property name="name" value="#{user.name}"/>
<property name="age" value="#{user2.age}"/>
<property name="car" ref="car"/>
</bean> <!-- 数组注入 -->
<bean name="cb" class="com.bean.CollectionBean">
<!-- 只有一个值时 -->
<!--<property name="arr" value="tom"/>-->
<!-- 多值多元素注入 -->
<property name="arr">
<array>
<value>xdzy</value>
<value>jady</value>
<ref bean="user3"/>
</array>
</property>
</bean> <!-- 集合注入 -->
<bean name="cb2" class="com.bean.CollectionBean">
<!-- 只有一个值时 -->
<!--<property name="list" value="tom"/>-->
<!-- 多值多元素注入 -->
<property name="list">
<list>
<value>xdzy</value>
<value>jady</value>
<ref bean="user3"/>
</list>
</property>
</bean> <!-- map注入 -->
<bean name="cb3" class="com.bean.CollectionBean">
<property name="map">
<map>
<entry key="name" value="xdzy"/>
<entry key="user" value-ref="user3"/>
<entry key-ref="user1" value-ref="user2"/>
</map>
</property>
</bean> <!-- 资源注入 -->
<bean name="cb4" class="com.bean.CollectionBean">
<property name="properties">
<props>
<prop key="driverClass">com.jdbc.mysql.Driver</prop>
<prop key="userName">admin</prop>
<prop key="password">123</prop>
</props>
</property>
</bean>
</beans>
spring的通知类型:
package com.aspect; import org.aspectj.lang.ProceedingJoinPoint;
/**
* @author: 肖德子裕
* @date: 2018/9/7 08:23
* @description: 通知
* 前置通知:目标方法运行之前
* 后置通知(如果出现异常不会调用):之后
* 环绕通知:之前之后
* 异常拦截通知:出现异常调用
* 后置通知(无论是否出现异常都会调用):之后
*/
public class MyAdvice {
//前置通知:目标方法运行之前
public void before(){
System.out.println("前置通知");
}
//后置通知(如果出现异常不会调用):之后
public void afterReturning(){
System.out.println("后置通知(如果出现异常不会调用)");
}
//环绕通知:之前之后
public Object around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知之前部分");
//调用目标方法
Object proceed=pjp.proceed();
System.out.println("环绕通知之后部分");
return proceed;
}
//异常拦截通知:出现异常调用
public void afterException(){
System.out.println("出现异常调用");
}
//后置通知(无论是否出现异常都会调用):之后
public void after(){
System.out.println("后置通知(无论是否出现异常都会调用)");
}
}
6)JDK动态代理与CGLIB动态代理
JDK动态代理:
package com.service; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* @author: 肖德子裕
* @date: 2018/9/6 20:25
* @description: 动态代理
* 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术
* 动态代理可对方法进行增强,如增加事务的打开与提交
* 个人理解:它是对service实现类里所有的方法进行了增强;
* 在不破坏原有结构的情况下,生成动态代理对象,对原有方法进行增强
*/
public class UserServiceProxyFactory implements InvocationHandler {
private UserService us; public UserServiceProxyFactory(UserService us) {
this.us = us;
} public UserService getUserServiceProxy(){
//生成动态代理
UserService userProxy=(UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(),
this);
//返回一个动态代理对象
return userProxy;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("打开事务");
Object invoke=method.invoke(us,args);
System.out.println("提交事务");
return invoke;
}
}
cglib动态代理:
package com.service; import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method;
/**
* @author: 肖德子裕
* @date: 2018/9/6 20:25
* @description: cglib代理
* 可以对任何类生成代理,对目标对象进行继承代理
*/
public class UserServiceProxyFactory2 implements MethodInterceptor {
public UserService getUserServiceProxy(){
//生成代理对象
Enhancer en=new Enhancer();
//对谁进行代理
en.setSuperclass(UserServiceImpl.class);
//代理要做什么
en.setCallback(this);
//创建代理对象
UserService us=(UserService) en.create();
return us;
} @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//打开事务
System.out.println("打开事务");
//调用原有方法
Object returnValue=methodProxy.invokeSuper(o,objects);
//提交事务
System.out.println("提交事务");
return returnValue;
}
}
复习宝典之Spring的更多相关文章
- 复习宝典之Redis
查看更多宝典,请点击<金三银四,你的专属面试宝典> 第八章:Redis Redis是一个key-value的nosql数据库.先存到内存中,会根据一定的策略持久化到磁盘,即使断电也不会丢失 ...
- 复习宝典之SpringMVC
查看更多宝典,请点击<金三银四,你的专属面试宝典> 第七章:SpringMVC MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(co ...
- 复习宝典之MyBatis
查看更多宝典,请点击<金三银四,你的专属面试宝典> 第五章:MyBatis MyBatis是一个可以自定义SQL.存储过程和高级映射的持久层框架. 1)创建sqlsession的流程 my ...
- spring复习 -day1:Spring简介 、 Spring容器 、 Spring IOC
Spring创建对象方法 创建对象过程: 第一步:添加SpringIOC环境 (1)在WebRoot/WEB-INT/lib文件夹下,引入SpringIOC配置环境的jar包 如图: (2)在sr ...
- 复习宝典之Mysql数据库
查看更多宝典,请点击<金三银四,你的专属面试宝典> 第一章:mysql数据库 1)mysql与mariaDb MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用 ...
- 复习宝典之Maven项目管理
查看更多宝典,请点击<金三银四,你的专属面试宝典> 第二章:Maven项目管理 Maven是基于项目对象模型(POM project object model),可以通过一小段描述信息(配 ...
- 复习宝典之Git分布式版本控制
查看更多宝典,请点击<金三银四,你的专属面试宝典> 第三章:Git分布式版本控制 1)git文件状态 git中的文件有以下几种状态: 未跟踪(untrack):表示文件为新增加的. 已修改 ...
- 软件架构期末复习(Struts2+Spring+Hibernate)
Struts2+Spring+Hibernate The Model-ViewController pattern in Struts2 is implemented with the followi ...
- Spring学习笔记1——基础知识 (转)
1.在java开发领域,Spring相对于EJB来说是一种轻量级的,非侵入性的Java开发框架,曾经有两本很畅销的书<Expert one-on-one J2EE Design and Deve ...
随机推荐
- 【Udacity】朴素贝叶斯
机器学习就像酿制葡萄酒--好的葡萄(数据)+好的酿酒方法(机器学习算法) 监督分类 supervised classification Features -->Labels 保留10%的数据作为 ...
- 二、Flex 布局教程:实例篇
注:本文转自大神阮一峰,自己加了少许改动~ 上一篇文章介绍了Flex布局的语法,今天介绍常见布局的Flex写法. 你会看到,不管是什么布局,Flex往往都可以几行命令搞定. 我只列出代码,详细的语法解 ...
- jquery attr和prop区别
<input type="checkbox" /> <script> $(function() { $('input').click(function() ...
- c# FTP操作类(转)
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Net ...
- javascript 同源策略及web安全
同源策略为什么而生? JS可以读取/修改网页的值. 一个浏览器中,打开一个银行网站和一个恶意网站,如果恶意网站能够对银行网站进行修改,那么就会很危险. 你打开了恶意网站和另一个网站,如果没有同源限制, ...
- SQLSERVER 中GO的作用
go 向 SQL Server 实用工具发出一批 Transact-SQL 语句结束的信号.go是把t-sql语句分批次执行.(一步成功了才会执行下一步,即一步一个go) BEGIN 和 END 语句 ...
- Python学习---远程执行命令
原则:发送一个接受一个 原理:发送执行命令的大小给客户端,客户端根据接受的大小判断是否全部接收了服务器sendall()发送的全部 利用send发送的全部数据都是bytes类型的,需要进行字符编码的转 ...
- January 24 2017 Week 4 Tuesday
Fashion changes, but style endures. 时尚会变迁,但风格会永恒. Please develop my personal style, in this way I ca ...
- MongoDB插入文档
db.collection.insertOne() 插入单个文档.db.collection.insertMany() 插入多个文档.db.collection.insert() 插入单/多个文档. ...
- CodeForces 91A Newspaper Headline
题目链接:CodeForces - 91A Newspaper Headline 官方题解: In this problem letters from s1 should be taken gree ...