Spring的理解

Spring总结:

引出Spring:解耦的思想:

问题:若把IEmployeeDAO的实现修改为:EmployeeDAOHibernateImpl,需要修改Java代码

----->简单工厂设计模式

----->把创建对象的职责交给工厂来管理.

小结:这样在更换持久层的技术,不会去修改源代码

 

IoC   Di  aop

发现问题:

service中要去处理事物相关的一些繁杂的操作:

---->找一个中介来去处理,service中只是执行和业务相关的操作

 

Spring能帮我们做什么:

.Spring能帮我们根据配置文件创建及组装对象之间的依赖关系。

.Spring 面向切面编程能帮助我们无耦合的实现日志记录,性能统计,安全控制。

.Spring能非常简单的帮我们管理数据库事务。

.Spring还提供了与第三方数据访问框架(如HibernateJPA)无缝集成,而且自己也提供了一套JDBC访问模板来方便数据库访问。

.Spring还提供与第三方Web(如Struts1/2JSF)框架无缝集成,而且自己也提供了一套Spring MVC框架,来方便web层搭建。

.Spring能方便的与Java EE(如Java Mail、任务调度)整合,与更多技术整合(比如缓存框架)。

 

Spring 的概述:

1. Spring是一个轻量级的DI/IoCAOP容器的开源框架,来源于Rod Johnson 在其著作《Expert one on one J2EE design and development》中阐述的部分理念和原型衍生而来。

2. 提倡”最少入侵” 的方式,意味着我们可以随时去安装和卸载spring

 

 

 

 

 

 

 

 

 

 

Spring常用的术语

1. 应用程序:是能完成我们所需要功能的成品,比如购物网站、OA系统。

 

2. 框架:是能完成一定功能的半成品,比如我们可以使用框架进行购物网站开发;框架做一部分功能,我们自己做一部分功能,这样应用程序就创建出来了。而且框架规定了你在开发应用程序时的整体架构,提供了一些基础功能,还规定了类和对象的如何创建、如何协作等,从而简化我们开发,让我们专注于业务逻辑开发。

 

3. 非侵入式设计:从框架角度可以这样理解,无需继承框架提供的类,这种设计就可以看作是非侵入式设计,如果继承了这些框架类,就是侵入设计,如果以后想更换框架之前写过的代码几乎无法重用,如果非侵入式设计则之前写过的代码仍然可以继续使用。

 

4. 轻量级及重量级:轻量级是相对于重量级而言的,轻量级一般就是非入侵性的、所依赖的东西非常少、资源占用非常少、部署简单等等,其实就是比较容易使用,而重量级正好相反。

 

5. POJOPOJOPlain Old Java Objects)简单的Java对象,它可以包含业务逻辑或持久化逻辑,但不担当任何特殊角色且不继承或不实现任何其它Java框架的类或接口。

 

6. 容器(Container):在日常生活中容器就是一种盛放东西的器具,从程序设计角度看就是装对象的的对象,因为存在放入、拿出等操作,所以容器还要管理对象的生命周期。

优势:

1. 低耦合/低侵入(降低组建之间的耦合度,实现软件各层之间的解耦)

2. 声明事物管理器

3. 方便集成其他框架的开发

4. 降低javaEE的开发难度

5. Spring框架中包括JavaEE 三层的每一层的解决方案(一站式)

 

 

 

Spring产品及其框架结构:

Spring Data

用于简化数据库访问,并支持云服务的开源框架。旨在统一和简化对各类型持久化存储, 而不拘泥是关系型数据库还是NoSQL数据存储。

Spring Batch

专门针对企业级系统中的日常批处理任务的轻量级框架,能够帮助开发者方便地开发出强壮、高效的批处理应用程序。

Spring Integration

Spring编程模型提供了一个支持企业集成模式(Enterprise Integration Patterns)的扩展,在应用程序中提供轻量级的消息机制,可以通过声明式的适配器与外部系统进行集成。

Spring Security(安全框架,shrio框架复杂一点)

早期称为Acegi,基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架;

Spring Roo,快速应用程序开发工具,可以在短时间内方便地构建应用程序。

Spring Mobile,对Spring MVC的扩展,旨在简化移动Web应用的开发。

Spring for Android,用于简化Android原生应用程序开发的Spring扩展。

等等

如下图所示:了解即可,清楚自己学什么

 

 

 

Spring框架架构:

Core Container(核心容器)包含有BeansCoreContextSpEL模块。

Data Access/Integration层包含有JDBCORMOXMJMSTransaction模块。

Web层包含了WebWeb-ServletWebSocketWeb-Porlet模块。

AOP模块提供了一个符合AOP联盟标准的面向切面编程的实现。

Test模块支持使用JUnitTestNGSpring组件进行测试。

 

 

 

 

Spring框架版本:

Spring2.5

¨ 拥抱驱动编程。

   支持SimpleJdbcTemplate的命名参数操作。

Spring3.x

    不再支持JDK1.4;

¨全面支持泛型。

    支持SpEL.

    支持WebServiceOXM

Spring4.x

  支持Java8,支持JavaEE6规范。

  泛型限定式依赖注入。

  Hibernate4的集成和事务提供更好的管理方案。

 

Spring框架包分析:

  现在都提倡使用Maven去下载Springjar:

下载地址:(直接输入)

http://repo.spring.io/libs-release-local/org/springframework/spring/

spring-framework-4.x.RELEASESpring核心组件。

   docs: Spring开发、帮助文档。

   libs: Spring核心组件的。jar包、源代码、文档。

   schema: Spring配置文件的schema约束文件。

spring-framework-3.x.RELEASE-dependenciesSpring依赖的第三方组件。

   包含了各大开源组织提供的依赖jar。比如apache common下的:dbcp.jar  pool.jar  logging.jar

Maven:

 

 

 

 

 

 

 

IoC:Inverse of Control(控制反转):

Spring的容器对象:BeanFactoryApplicationContext对象.

BeanFactory:是Spring中最底层的接口,只提供了最简单的IoC功能,负责配置,创建和管理bean

在实际开发中,一般不使用BeanFactory,而推荐使用ApplicationContext(应用上下文),原因如下。

BeanFactoryApplicationContext的区别

1ApplicationContext继承了BeanFactory,拥有了基本的IoC功能;

2、除此之外,ApplicationContext还提供了以下的功能:

   ①、支持国际化;

   ②、支持消息机制;

   ③、支持统一的资源加载;

   ④、支持AOP功能;

ApplicationContext常见实现类:ClassPathXmlApplicationContext:读取classpath中的资源.

 

bean的创建时机:

1.ApplicationContext在加载的时候就会创建所有的beanWeb应用建议),在启动Tomcat,创建好所有的bean对象.

2.BeanFactory需要等到拿bean的时候才会创建bean(桌面程序)

 

 

优化性能

延迟实例化的配置:

针对于当前xml中所有的bean

<beans default-lazy-init="default | false | true">

 

针对于指定的bean:

<bean lazy-init="default | false | true">

 

 

 

 

 

 

 

 

 

 

 

 

 

 

方式一:

使用xml的形式:

<bean标签的继承>

<bean id=parent abstract=true >

<property  name=””  value=”” ></property>(基本类型)

<property  name=””  ref=””   ></property>(引用类型)

</bean>

<bean  id=””   class=””   init-method=””   destory-method=”” scope=””  parent=”” ></bean>

1. <bean>id/name:

Spring配置中,idname属性都可以定义bean元素的名称,不同的是:

lid属性,遵守XML语法ID约束。Spring3.1开始,id属性不再是ID类型了,而是String类型,也就是说id属性也可以使用“/”开头了,而bean元素的id的唯一性由容器负责检查。

lname属性,就可以使用很多特殊字符,比如在SpringStruts1Spring MVC的整合中,就得使用name属性来的定义bean的名称。当然也可以使用name属性为<bean/>元素起多个别名,多个别名之间使用逗号或空格隔开,在代码中依然使用BeanFactory对象.getBean(...)方法获取。

 

 注意:通俗的理解:

Id表示的是唯一的标识(运行原理结合下的di),class表示的是类的权限类名:把哪个类交给spring去管理,帮助我们去创建,只需要在ApplicationContext容器中使用getBean(“id”,.class)方法就可以获得对象

 

2. <bean>元素的抽取

创建一个<bean> 定义为abstrcat(抽象)不必要去实现这个类(不用去写class),把多个bean对象中相同类型的属性提取出来,(化繁为简),<bean>标签只需要定义一个parent属性给其一个id,xml的代码抽取

 

 

 

 

 

 

 

标签具有的属性:

1. scope=””(理解:要把action设置为多例的模式,单例存在的问题:线程不安全的问题,多线程并发访问同一资源对象,产生线程的阻塞,堵死等现象)

前台使用的技术是springmvc-->  controller为单例

........使用................struts2-------->  action为多例 ,在使用xml配置的时候一定要配置生命周期

在开发中主要使用 scope="singleton"scope="prototype"

对于Struts2中的Action使用prototype类型,其他使用singleton

 

 

 

(图看不懂了打电话)

 

2. 初始化和销毁的方法:

简而言之:在把对象交给spring的时候,在调用构造器之后想要初始化,在容器销毁之前,要执行销毁的操作,在其对应的类中去创建对应的方法

重点:xml当中的配置:

init-methodbean生命周期初始化方法,对象创建后就进行调用

destroy-method:容器被销毁的时候,如果bean被容器管理,会调用该方法。

scope="prototype",那么容器只负责创建和初始化,它并不会被spring容器管理

 

 

方式二:

使用注解的方式:

推理思想:xml中有的方式,方法,那么在注解当中也一定会存在,使用标签来完成IoC,就必须有IoC标签的解析器 :context:component-scan(IoC扫描器)

 

1. .bean组件版型标签(规范!!!!!!!!)

@Service用于标注业务层组件、

@Controller用于标注控制层组件(如struts中的action)、

@Repository用于标注数据访问组件,即DAO组件。

@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

理解:相当于<bean>中的class (“”)-->id]

 

2. @Scope("prototype")  

***这两个注解在方法上贴

3. @PostConstruct (在构造器之后执行的方法:表示的是初始化的方法)

4. @PreDestroy(表示在容器销毁之前执行的方法,表示的是销毁的方法)

 

选用xml还是注解:

1),Annotation(注解):使用方便,XML文件很小,但是,依赖关系又重新回到了代码当中;

2),XML:使用稍微复杂,但是,代码很干净,代码不会很任何框架产生关系;XML安全;

 

 

 

了解:

使用@Component的限制:

  1),不能运用到静态工厂方法和实例工厂方法,但是可以使用到FactoryBean;

  2),对于没有源代码的类(框架内部的预定义类),只能用XML配置;必然DataSource就只能使用XML方式来做IOC.

 

 

 

 

 

 

 

 

注意事项,以及拓展:

底层是如何去创建这个类的?

使用了工厂去创建,框架的底层通过反射去创建对象

 

 

 

 

DIDependency Injection(依赖注入)

简而言之:Spring创建对象的时候,把值去注入到属性当中去

注入方式:

   1):手动装配(XML方式),必须掌握.

   2):自动装配(注解方式),必须掌握.

自动装配(XML方式),了解.

 

(1) :手动装配(XML方式) 必须通过对应的set方法

简单数据类型,使用的是value

符合数据类型,使用的是ref(理解,自定义的类,或者交给容器管理的其他类)

集合数据类型:使用集合元素

Value:

<property name=””  value=””/>

Ref:

<property name=””  ref=””/>

List

<property name=”” >

<set> <value></value> </set>

<list> <value></value> </list>

<array> <value></value> </array>

<map>

<entry key = “” value=””>

</map>

</property >

 

 

 

 

 

 

 

 

(2) 注解的方式:

使用Spring框架自身提供的标签:Autowired

---------------------------------------------------------

AutowiredQualifier标签:

1. 通过@Autowired标签可以让Spring自动的把属性需要的对象从Spring容器中找出来,并注入(设置)给该属性。

2. <context:annotation-config />   开启di扫描器

3. @Autowired标签贴在字段或者setter方法上。

4. @Autowired可以同时为一个属性注入多个对象。

public void setXxx(OtherBean1 other1,OtherBean2 other2) {}

5. 使用@Autowired标签可以注入Spring内置的重要对象,比如BeanFactoryApplicationContext

6. 默认情况下@Autowired标签必须要能找到对应的对象,否则报错。不过,可使用required=false来避免该问题:@Autowired(required=false)

 

@Autowiredbean的方式:

1)、首先按照依赖对象的类型找(也就是class),如果找到则使用setter方法或者字段直接注入;

2)、如果在Spring上下文中找到多个匹配的类型,再按照名字(name)去找,如果没有匹配则报错;

3)、可以通过使用@Qualifier("otherBean")标签来规定依赖对象按照beanid+类型去找;

 

使用JavaEE规范提供的标签:Resource

---------------------------------------------------------

@Resource标签:

(1) @Resource标签是JavaEE规范的标签;

(2) @Resource标签也可以作用于字段或者setter方法;

 

(3) 也可以使用@Resource标签注入一些spring内置的重要对象,比如BeanFactory.ApplicationContext;

(4) @Resource必须要求有匹配的对象;

(5) <context:annotation-config>既引入了@Autowired标签的解析器,也引入了@Resource的解析器;

 

  @Resource标签找bean的方式:

  1)、首先按照名字去找,如果找到,就使用setter或者字段注入;

  2)、如果按照名字找不到,再按照类型去找,但如果找到多个匹配类型,报错;

  3)、可以直接使用name属性指定bean的名称;但是,如果指定的name,就只能按照name去找,如果找不到,就不会再按照类型去找;

 

动态代理和静态代理

 

静态代理:在程序运行前就已经存在代理类的字节码文件,代理对象和真实对象的关系在运行前就确定了。

动态代理:动态代理类是在程序运行期间由JVM通过反射等机制动态的生成的,所以不存在代理类的字节码文件。代理对象和真实对象的关系是在程序运行事情才确定的。

静态代理优缺点:

优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。

缺点:

n1.代理对象的某个接口只服务于某一种类型的对象,也就是说每一个真实对象都得创建一个代理对象。

n2.如果需要代理的方法很多,则要为每一种方法都进行代理处理。

n3.如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。

 

核心:1.JDK的动态代理

2.CGLIBE的动态代理

 

JDK:思想:在使用动态代理的时候就不需要去手动的创建代理的对象,而是交给底层去创建代理对象..通过字节码的方式去JVM去创建代理对象,那么问题随之而来,jvm创建的代理对象是不知道我们要对什么类进行什么操作,在什么时候..需要去定义处理器,代理对象去调用处理器,就能够实现功能模块的处理

------------>:处理器:其实就是事物的处理,以及真实业务的操作

 

 

jdk动态代理操作步骤

① 实现InvocationHandler接口,创建自己增强代码的处理器。

② 给Proxy类提供ClassLoader对象和代理接口类型数组,创建动态代理对象。

③ 在处理器中实现增强操作。

---------------------------------

JDK动态代理总结:

1,JAVA动态代理是使用java.lang.reflect包中的Proxy类与InvocationHandler接口这两个来完成的。

2,要使用JDK动态代理,必须要定义接口。

3,JDK动态代理将会拦截所有pubic的方法(因为只能调用接口中定义的方法),这样即使在接口中增加了新的方法,不用修改代码也会被拦截。

4,如果只想拦截一部分方法,可以在invoke方法中对要执行的方法名进行判断。

 

 

 

 

 

 

JDK动态代理API分析:

1java.lang.reflect.Proxy :

Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。

主要方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler hanlder)

方法职责:为指定类加载器、一组接口及调用处理器生成动态代理类实例

参数:

   loader :类加载器

   interfaces :模拟的接口

   hanlder :代理执行处理器

 

返回:动态生成的代理对象

2java.lang.reflect.InvocationHandler接口:

public Object invoke(Object proxy, Method method, Object[] args)

方法职责:负责集中处理动态代理类上的所有方法调用

参数:

    proxy :生成的代理对象

    method :当前调用的真实方法对象

    args :当前调用方法的实参

 

 

 

CGLIBE:

针对于没有接口的类,如何做代理:cglibjavassist都是针对没有接口,做动态代理的.

原理: 对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

 

CGLIB代理总结:

1,CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。

2,要求类不能是final的,要拦截的方法要是非final、非static、非private的。

3,动态代理的最小单位是类(所有类中的方法都会被处理);

 

 

Spring中:

n若目标对象实现了若干接口,Spring就会使用JDK动态代理。

n若目标对象没有实现任何接口,Spring就使用CGLIB库生成目标对象的子类。

对接口创建代理优于对类创建代理,因为会产生更加松耦合的系统,也更符合面向接口编程规范。

 

 

 

 

 

 

AOP:Aspect oritention programming(面向切面编程)

 

Aop的优势:

降低代码的耦合度

体现责任分离,使service更专注与业务逻辑的处理,而不是去处理与其无关事件

 

AOP的目的:

AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,

便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。

AOP的优势:

降低模块的耦合度、使系统容易扩展、更好的代码复用性

   说人话: 把多个方法前/后的共同代码抽离出来,使用动态代理机制来控制,先执行抽离出来的代码,再执行每一个真实方法.

 

SpringAOP使用动态代理实现:

如果一个类实现了接口,那么spring就使用JDK的动态代理完成AOP;

如果一个类没有实现接口,那么spring就是用cglib完成AOP;

AOP当中的概念:

1、切入点(Pointcut):在哪些类,哪些方法上切入(where);

2、增强(Advice):早期翻译为通知,在方法执行的什么时机(when:方法前/方法后/方法前后)做什么(what:增强的功能);

3、切面(Aspect):切面=切入点+通知,通俗点就是:什么时机,什么地点,做什么!

4、织入(Weaving):把切面加入到对象,并创建出代理对象的过程。(该过程由Spring来完成)。

 

Aop的应用:事务;日志

 

 

 

AspectJ切入点语法如下:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?    

            name-pattern(param-pattern)throws-pattern?)

翻译如下:

execution(<访问修饰符>? <返回类型> <声明类型>? <方法名>(<参数>) <异常>?)

 

 

 

Spring中的各种增强

 

 

各种不同的增强:

aop:before(前置增强):在方法执行之前执行增强;

aop:after-returning(后置增强):在方法正常执行完成之后执行增强;

aop:after-throwing(异常增强):在方法抛出异常退出时执行增强;

aop:after(最终增强):在方法执行之后执行,相当于在finally里面执行;可以通过配置throwing来获得拦截到的异常信息

aop:around(环绕增强):最强大的一种增强类型。 环绕增强可以在方法调用前后完成自定义的行为,环绕通知有两个要求,

   1.方法必须要返回一个Object(返回的结果)

   2.方法的第一个参数必须是ProceedingJoinPoint(可以继续向下传递的切入点)

(这个也就是when:如何去增强)

 

 

 

 

方式一

 

 

方式二:(使用一个自定义的事物管理器举例说明)

 

Spring对事物的支持

 

Spring的事务管理主要包括3个接口:

TransactionDefinition:封装事务的隔离级别,超时时间,是否为只读事务和事务的隔离级别和传播规则等事务属性,可通过XML配置具体信息。

PlatformTransactionManager:根据TransactionDefinition提供的事务属性配置信息,创建事务。

TransactionStatus:封装了事务的具体运行状态。比如,是否是新开启事务,是否已经提交事务,设置当前事务为rollback-only等。

 

Spring支持编程式事务管理和声明式事务管理。

--------------------------------------------------------------------------------

l编程式事务管理:事务和业务代码耦合度太高。

l声明式事务管理:侵入性小,把事务从业务代码中抽离出来,提供维护性。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Spring的事务管理:

1.  PlatformTransactionManager:接口统一抽象处理事务操作相关的方法;

1):TransactionStatus getTransaction(TransactionDefinition definition)

根据事务定义信息从事务环境中返回一个已存在的事务,或者创建一个新的事务,并用TransactionStatus描述该事务的状态。

 

ü 2):void commit(TransactionStatus status)

根据事务的状态提交事务,如果事务状态已经标识为rollback-only,该方法执行回滚事务的操作。

 

ü 3):void rollback(TransactionStatus status)

将事务回滚,当commit方法抛出异常时,rollback会被隐式调用

 

2.  在使用spring管理事务的时候,首先得告诉spring使用哪一个事务管理器; 看图

 

3,常用的事务管理器:

   DataSourceTransactionManager:使用JDBC,MyBatis的事务管理器;

   HibernateTransactionManager:使用Hibernate的事务管理器;

 

 

 

 

 

 

 

 

 

 

 

基于xml的配置

 

 

 

注解的方式

@Transactional

但是要开启注解扫描器

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

思考 Mapper

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值