查看更多宝典,请点击《金三银四,你的专属面试宝典》html
Spring容器是Spring的核心,一切Spring bean都存储在Spring容器内,并由其经过IoC技术管理。Spring容器也就是一个bean工厂(BeanFactory)。应用中bean的实例化,获取,销毁等都是由这个bean工厂管理的。java
org.springframework.context.ApplicationContext接口用于完成容器的配置,初始化,管理bean。一个Spring容器就是某个实现了ApplicationContext接口的类的实例。也就是说,从代码层面,Spring容器其实就是一个ApplicationContext。mysql
在普通的JAVA工程中,咱们能够经过代码显式new一个ClassPathXmlApplicationContext或者FileSystemXmlApplicationContext来初始化一个Spring容器。程序员
在Web工程中,咱们通常是经过配置web.xml的方式来初始化Spring容器。web
轻量--从大小与开销两方面而言Spring都是轻量的。完整的Spring框架能够在一个大小只有1MB多的JAR文件里发布。而且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。面试
控制反转-Spring经过一种称做控制反转(IoC)的技术促进了低耦合。当应用了IoC,一个对象依赖的其它对象会经过被动的方式传递进来,而不是这个对象本身建立或者查找依赖对象。你能够认为IoC与JNDI相反--不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。spring
面向切面--Spring提供了面向切面编程的丰富支持,容许经过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该作的--完成业务逻辑--仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。sql
容器--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中的各类模块提供了基础支持。
spring容器工厂:spring对全部对象均可以进行管理,而后经过单例模式建立一个全局惟一的一个实例对象,经过工厂模式在调用注入的接口时实例化对象。
Spring模式包含:单例模式和工厂模式
单例模式: a.单例模式限制了类实例的建立,但采用这种模式设计的类,能够保证仅有一个实例,并可提供访问该实例的全局访问点。b.J2EE应用的大量组件,都须要保证一个类只有一个实例,好比数据库引擎访问只有一个。c.可是更多时候,为了提升性能,程序应尽可能减小Java 对象的建立和销毁时的开销。使用单例模式可避免Java 类被屡次实例化。d. 为了防止单态模式的类被屡次实例化,应将类的构造器设成私有,这样就保证了只能经过静态方法得到类实例。
工厂模式:a.工厂模式是根据调用数据返回某个类的一个实例,此类能够是多个类的某一个类。b.一般,这些类知足共同的规则(接口)或父类。调用者只关心工厂生产的实例是否知足某种规范,即实现的某个接口是否可供本身正常调用(调用者仅仅使用)。c.该模式给对象之间做出了清晰的角色划分,下降程序的耦合。d.接口产生的所有实例一般用于实现相同接口,接口里定义了所有实例共同拥有的方法,这些方法在不一样的实现类中实现的方式不一样。f.从而使程序调用者无须关心方法的具体实现,下降了系统异构的代价。
IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导咱们如何设计出松耦合、更优良的程序。传统应用程序都是由咱们在类内部主动建立依赖对象,从而致使类与类之间高耦合,难于测试;有了IoC容器后,把建立和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,因此对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得很是灵活。
其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序本来是老大,要获取什么资源都是主动出击,可是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来建立并注入它所须要的资源了。
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找咱们,咱们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并不是为软件系统带来更多功能,而是为了提高组件重用的频率,并为系统搭建一个灵活、可扩展的平台。经过依赖注入机制,咱们只须要经过简单的配置,而无需任何代码就可指定目标须要的资源,完成自身的业务逻辑,而不须要关心具体的资源来自何处,由谁实现。
IoC(Inversion of Control,控制反转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来讲,就是由spring来负责控制对象的生命周期和对象间的关系。
Spring所倡导的开发方式就是如此,全部的类都会在spring容器中登记,告诉spring你是个什么东西,你须要什么东西,而后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其余须要你的东西。全部的类的建立、销毁都由 spring来控制,也就是说控制对象生存周期的再也不是引用它的对象,而是spring。对于某个具体的对象而言,之前是它控制其余对象,如今是全部对象都被spring控制,因此这叫控制反转。
IoC的一个重点是在系统运行中,动态的向某个对象提供它所须要的其余对象。这一点是经过DI(Dependency Injection,依赖注入)来实现的。
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 代理
spring的一些基本概念:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
5
6 <!-- spring:管理对象的容器 -->
7 <!-- spring IOC:控制反转,经过spring建立对象(无需手动建立) -->
8 <!-- DI:依赖注入;就是给对象的某些属性赋值 -->
9
10 <!-- 将User对象交给spring管理 -->
11 <!-- bean元素:描述须要spring管理的对象;name属性:给对象取个别名,获取对象时须要;
12 class属性:被管理对象的完整类名;id属性:与name属性如出一辙,不可重复,不能使用特殊字符(所以要name)-->
13 <!-- 建立方式一:spring调用无参构造建立对象 -->
14 <!-- scope:singleton:表示单例对象,在spring容器中只会存在一个实例 -->
15 <!-- scope:prototype:表示多例对象,每次获取都会建立一个新的对象;整合struts2时必须为多例 -->
16 <!-- 生命周期方法配置init,destroy -->
17 <bean name="user" class="com.bean.User" scope="singleton" init-method="init" destroy-method="destroy"></bean>
18
19 <!-- 建立方式二:经过静态工厂的某个方法建立一个user对象 -->
20 <bean name="user1" class="com.bean.UserFactory" factory-method="createUser"></bean>
21
22 <!-- 建立方式三:实例工厂建立对象 -->
23 <bean name="user2" factory-bean="userFactory" factory-method="createUser2"></bean>
24 <bean name="userFactory" class="com.bean.UserFactory"></bean>
25
26 <!-- 模块化配置,能够导入其余spring配置文件 -->
27 <!--<import resource="applicationContext.xml"/>-->
28 </beans>
spring依赖注入方式:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:p="http://www.springframework.org/schema/p"
5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
6
7 <!-- set方式注入 -->
8 <bean name="user" class="com.bean.User">
9 <!-- 值类型注入 -->
10 <property name="name" value="xdzy"/>
11 <property name="age" value="18"/>
12 <!-- 引用类型注入 -->
13 <property name="car" ref="car"/>
14 </bean>
15
16 <!-- 将car对象配置到spring容器 -->
17 <bean name="car" class="com.bean.Car">
18 <property name="name" value="兰博基尼"/>
19 <property name="color" value="红色"/>
20 </bean>
21
22 <!-- 构造函数注入 -->
23 <bean name="user1" class="com.bean.User">
24 <!-- 当构造方法参数位置不一样,能够经过index肯定参数位置 -->
25 <!-- 当构造方法参数类型不一样,能够经过type肯定参数类型 -->
26 <constructor-arg name="name" value="xdzy" index="0" type="java.lang.String"/>
27 <constructor-arg name="car" ref="car"/>
28 </bean>
29
30 <!-- p属性注入 -->
31 <!-- 需加入xmlns:p="http://www.springframework.org/schema/p" -->
32 <bean name="user2" class="com.bean.User" p:name="xdzy" p:age="18" p:car-ref="car"/>
33
34 <!-- spel表达式注入;能够实现动态注入 -->
35 <bean name="user3" class="com.bean.User">
36 <property name="name" value="#{user.name}"/>
37 <property name="age" value="#{user2.age}"/>
38 <property name="car" ref="car"/>
39 </bean>
40
41 <!-- 数组注入 -->
42 <bean name="cb" class="com.bean.CollectionBean">
43 <!-- 只有一个值时 -->
44 <!--<property name="arr" value="tom"/>-->
45 <!-- 多值多元素注入 -->
46 <property name="arr">
47 <array>
48 <value>xdzy</value>
49 <value>jady</value>
50 <ref bean="user3"/>
51 </array>
52 </property>
53 </bean>
54
55 <!-- 集合注入 -->
56 <bean name="cb2" class="com.bean.CollectionBean">
57 <!-- 只有一个值时 -->
58 <!--<property name="list" value="tom"/>-->
59 <!-- 多值多元素注入 -->
60 <property name="list">
61 <list>
62 <value>xdzy</value>
63 <value>jady</value>
64 <ref bean="user3"/>
65 </list>
66 </property>
67 </bean>
68
69 <!-- map注入 -->
70 <bean name="cb3" class="com.bean.CollectionBean">
71 <property name="map">
72 <map>
73 <entry key="name" value="xdzy"/>
74 <entry key="user" value-ref="user3"/>
75 <entry key-ref="user1" value-ref="user2"/>
76 </map>
77 </property>
78 </bean>
79
80 <!-- 资源注入 -->
81 <bean name="cb4" class="com.bean.CollectionBean">
82 <property name="properties">
83 <props>
84 <prop key="driverClass">com.jdbc.mysql.Driver</prop>
85 <prop key="userName">admin</prop>
86 <prop key="password">123</prop>
87 </props>
88 </property>
89 </bean>
90 </beans>
spring的通知类型:
1 package com.aspect;
2
3 import org.aspectj.lang.ProceedingJoinPoint;
4 /**
5 * @author: 肖德子裕
6 * @date: 2018/9/7 08:23
7 * @description: 通知
8 * 前置通知:目标方法运行以前
9 * 后置通知(若是出现异常不会调用):以后
10 * 环绕通知:以前以后
11 * 异常拦截通知:出现异常调用
12 * 后置通知(不管是否出现异常都会调用):以后
13 */
14 public class MyAdvice {
15 //前置通知:目标方法运行以前
16 public void before(){
17 System.out.println("前置通知");
18 }
19 //后置通知(若是出现异常不会调用):以后
20 public void afterReturning(){
21 System.out.println("后置通知(若是出现异常不会调用)");
22 }
23 //环绕通知:以前以后
24 public Object around(ProceedingJoinPoint pjp) throws Throwable{
25 System.out.println("环绕通知以前部分");
26 //调用目标方法
27 Object proceed=pjp.proceed();
28 System.out.println("环绕通知以后部分");
29 return proceed;
30 }
31 //异常拦截通知:出现异常调用
32 public void afterException(){
33 System.out.println("出现异常调用");
34 }
35 //后置通知(不管是否出现异常都会调用):以后
36 public void after(){
37 System.out.println("后置通知(不管是否出现异常都会调用)");
38 }
39 }
JDK动态代理:
1 package com.service;
2
3 import java.lang.reflect.InvocationHandler;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Proxy;
6
7 /**
8 * @author: 肖德子裕
9 * @date: 2018/9/6 20:25
10 * @description: 动态代理
11 * 被代理对象必需要实现接口,才能产生代理对象,若是没有接口将不能使用动态代理技术
12 * 动态代理可对方法进行加强,如增长事务的打开与提交
13 * 我的理解:它是对service实现类里全部的方法进行了加强;
14 * 在不破坏原有结构的状况下,生成动态代理对象,对原有方法进行加强
15 */
16 public class UserServiceProxyFactory implements InvocationHandler {
17 private UserService us;
18
19 public UserServiceProxyFactory(UserService us) {
20 this.us = us;
21 }
22
23 public UserService getUserServiceProxy(){
24 //生成动态代理
25 UserService userProxy=(UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
26 UserServiceImpl.class.getInterfaces(),
27 this);
28 //返回一个动态代理对象
29 return userProxy;
30 }
31
32 @Override
33 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
34 System.out.println("打开事务");
35 Object invoke=method.invoke(us,args);
36 System.out.println("提交事务");
37 return invoke;
38 }
39 }
cglib动态代理:
1 package com.service;
2
3 import org.springframework.cglib.proxy.Enhancer;
4 import org.springframework.cglib.proxy.MethodInterceptor;
5 import org.springframework.cglib.proxy.MethodProxy;
6
7 import java.lang.reflect.Method;
8 /**
9 * @author: 肖德子裕
10 * @date: 2018/9/6 20:25
11 * @description: cglib代理
12 * 能够对任何类生成代理,对目标对象进行继承代理
13 */
14 public class UserServiceProxyFactory2 implements MethodInterceptor {
15 public UserService getUserServiceProxy(){
16 //生成代理对象
17 Enhancer en=new Enhancer();
18 //对谁进行代理
19 en.setSuperclass(UserServiceImpl.class);
20 //代理要作什么
21 en.setCallback(this);
22 //建立代理对象
23 UserService us=(UserService) en.create();
24 return us;
25 }
26
27 @Override
28 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
29 //打开事务
30 System.out.println("打开事务");
31 //调用原有方法
32 Object returnValue=methodProxy.invokeSuper(o,objects);
33 //提交事务
34 System.out.println("提交事务");
35 return returnValue;
36 }
37 }