Spring

什么是Spring

Spring是J2EE应用程序轻量级框架,它一种非侵入的方式来管理你的代码。

IOC(Inversion of Control)控制反转

对象创建责任的反转,在Spring中的BeanFactory是IOC容器的核心接口,
负责实力恶化,定位,配置应用程序中的对象及建立这些对象间的依赖。
XmlBeanFactory实现BeanFactory接口,通过获取xml配置文件数据,
组成应用对象及对象间的依赖关系。
Spring中三种注入方式:set注入(必须要有无参构造方法),接口注入,构造方法注入

  • xml 方式
<bean id="helloWorld" // 标识符
                class="com.test.HelloWorld" // 类全名
                lazy-init="true" // 延迟初始化,第一次获取时才初始化,默认是false(spring容器启动时就初始化)
                scope="prototype" // 添加此属性后bean可以创建多实例(spring默认创建的是单列),
                                     但是spring不会再管理这些实例的生命周期,谁用 谁管理。
                                     而且添加此属性后lazy_init="true"失效。
                init-method="init" // 实例化bean之后调用的方法
                destroy-method="destroy" // 销毁bean之前调用的方法     
                <!-- 
                    property描述的就是bean中的属性
                       name属性就是描述属性的名称
                       value就是值   如果是基本属性(String),就用value赋值
                       ref  如果是引用类型,用ref赋值
                -->
                <property name="pid" value="1"></property>
                <property name="name" value="王二麻子"></property>
                <property name="student" ref="student"></property>
                // 对象作为属性,也可以这样:
               <!-- <property name="student">
                      <ref bean="student"/>
                    </property> -->
                 <!-- 
                    constructor-arg  代表某一个构造器的参数
                      index 构造器参数的下标
                      value
                      ref
                      type  类型
                 -->
                <constructor-arg index="0" value="1" type="java.lang.String"></constructor-arg>
                <constructor-arg index="1" ref="student"></constructor-arg>
                ></bean>
            <alias name="helloWorld" alias="骑士"/>
            <alias name="helloWorld" alias="皇马"/>
            <alias name="helloWorld" alias="中国女排"/> // 别名
            <!-- 工厂方法创建实例 -->
            <bean id="helloWorld2" 
                class="com.test.HelloWorldFactory" 
                factory-method="getInstance"></bean>
            <bean id="helloWorldFactory" class="com.test.HelloWorldFactory2"></bean>
            <!-- 
                factory-bean指向了实力工厂的bean
                factory-method实例工厂对象的方法
             -->
            <bean id="helloWorld3" factory-bean="helloWorldFactory" factory-method="getInstance"></bean>
             <!-- 工厂方法创建 -->
             ApplicationContext context = 
                         new ClassPathXmlApplicationContext("applicationContext.xml");
                HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld");
                HelloWorld helloWorld2 = (HelloWorld)context.getBean("骑士");
                HelloWorld helloWorld3 = (HelloWorld)context.getBean("helloWorld2");
                HelloWorld helloWorld4 = (HelloWorld)context.getBean("helloWorld3");
                   如果scope不是"prototype"的话获取的都是一个对象
  • 注解
    1. 配置文件中加入<context:annotation-config></context:annotation-config>
      @Autowired/@Resource:这两个注解的区别是:@Autowired 默认按类型装配,
      @Resource默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
      都可以作用在字段上和setter方法上。
      @Autowired:注解是按类型装配依赖对象默认情况下它要求依赖对象必须存在,
          如果允许null值,可以设置它required属性为false。
          如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。
      @Resource注解默认按名称装配。
          名称可以通过@Resource的name属性指定,如果没有指定name属性,
          当注解标注在字段上,即默认取字段的名称作为bean名称寻找依赖对象
          当注解标注在属性的setter方法上,即默认取属性名作为bean名称寻找依赖对象。
          注意:如果没有指定name属性,并且按照默认的名称找不到依赖对象时, @Resource注解会回退到按类型装配。但一旦指定了name属性,就只能按名称装配了。
      @PostConstruct :指定Bean的初始化方法
      @PreDestroy :指定Bean的销毁方法
    2. 扫描方式,在配置文件中加入 <context:component-scan base-package="cn.test"/>
      其中base-package为需要扫描的包(含子包)。
      1、在使用组件扫描元素时,AutowiredAnnotationBeanPostProcessor 和CommonAnnotationBeanPostProcessor会隐式地被包括进来。 也就是说,连个组件都会被自动检测并织入 - 所有这一切都不需要在XML中提供任何bean配置元数据。
      2、功能介绍
      @Service用于标注业务层组件、
      @Controller用于标注控制层组件(如struts中的action)、
      @Repository用于标注数据访问组件,即DAO组件。
      而@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

AOP面向切面编程

AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都是如此,这种散布在各处的无关的代码被称为横切(cross cutting),在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。

使用"横切"技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

  • AOP核心概念

    1、横切关注点

      对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点
    

    2、切面(aspect)

      类是对物体特征的抽象,切面就是对横切关注点的抽象
    

    3、连接点(joinpoint)

      被拦截到的点,因为Spring只支持方法类型的连接点,  
      所以在Spring中连接点指的就是被拦截到的方法,       
      实际上连接点还可以是字段或者构造器
    

    4、切入点(pointcut)

      对连接点进行拦截的定义
    

    5、通知(advice)

      所谓通知指的就是指拦截到连接点之后要执行的代码,  
      通知分为前置、后置、异常、最终、环绕通知五类
    

    6、目标对象

      代理的目标对象
    

    7、织入(weave)

      将切面应用到目标对象并导致代理对象创建的过程
    

    8、引入(introduction)

      在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段      
    
<aop:config>
        <aop:pointcut 
               // 切入点表达式
            expression="execution(* com.test.PersonDaoImpl.*(..))" 
            id="perform"/>
        <aop:aspect ref="transaction">
            <!-- 
                前置通知
                    1、在目标方法执行之前
                    2、前置通知中,方法有一个参数JoinPoint
             -->
            <!-- 
            <aop:before method="beginTransaction" pointcut-ref="perform"/>
             -->
            <!-- 
                后置通知
                   1、在目标方法执行之后
                   2、能够获取目标方法的返回值
                       returning="val"
                   3、如果目标方法产生异常,则后置通知不再执行
             -->
            <!-- 
            <aop:after-returning method="commit" pointcut-ref="perform" returning="val"/>
             -->
            <!-- 
                异常通知
                          获取目标方法抛出的异常信息
                    throwing="ex"
             -->
            <aop:after-throwing method="throwingMethod" pointcut-ref="perform" throwing="ex"/>
            <!-- 
                最终通知
             -->
            <aop:after method="finallyMethod" pointcut-ref="perform"/>
            <!-- 
                环绕通知
                    能够控制目标方法的执行
                    环绕通知可以有返回值,这个返回值就是代理对象的方法的返回值
                    前置通知和后置通知只能在目标方法执行之前和之后加代码,但是不能控制目标方法的执行
             -->
            <aop:around method="aroundMethod" pointcut-ref="perform"/>
        </aop:aspect>
    </aop:config>
常用切入点表示式
任意公共方法的执行:
execution(public * *(..))
任何一个名字以“set”开始的方法的执行:
execution(* set*(..))
AccountService接口定义的任意方法的执行:
execution(* com.xyz.service.AccountService.*(..))
在service包中定义的任意方法的执行:
execution(* com.xyz.service.*.*(..))
在service包或其子包中定义的任意方法的执行:
execution(* com.xyz.service..*.*(..))
在service包中的任意连接点(在Spring AOP中只是方法执行):
within(com.xyz.service.*)
在service包或其子包中的任意连接点(在Spring AOP中只是方法执行):
within(com.xyz.service..*)
实现了AccountService接口的代理对象的任意连接点 (在Spring AOP中只是方法执行):
this(com.xyz.service.AccountService)
'this'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得代理对象在通知体内可用。
实现AccountService接口的目标对象的任意连接点 (在Spring AOP中只是方法执行):
target(com.xyz.service.AccountService)
'target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得目标对象在通知体内可用。
任何一个只接受一个参数,并且运行时所传入的参数是Serializable 接口的连接点(在Spring AOP中只是方法执行)
args(java.io.Serializable)
'args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得方法参数在通知体内可用。
请注意在例子中给出的切入点不同于 execution(* *(java.io.Serializable)): args版本只有在动态运行时候传入参数是Serializable时才匹配,而execution版本在方法签名中声明只有一个 Serializable类型的参数时候匹配。
目标对象中有一个 @Transactional 注解的任意连接点 (在Spring AOP中只是方法执行)
@target(org.springframework.transaction.annotation.Transactional)
'@target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
任何一个目标对象声明的类型有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
@within(org.springframework.transaction.annotation.Transactional)
'@within'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
任何一个执行的方法有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行)
@annotation(org.springframework.transaction.annotation.Transactional)
'@annotation'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
任何一个只接受一个参数,并且运行时所传入的参数类型具有@Classified 注解的连接点(在Spring AOP中只是方法执行)
@args(com.xyz.security.Classified)
'@args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
任何一个在名为'tradeService'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
bean(tradeService)
任何一个在名字匹配通配符表达式'*Service'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
bean(*Service)
Spring JDBC事务管理
<!-- 
        事务管理器
     -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource">
            <ref bean="dataSource"/>
        </property>
    </bean>
    
    <!-- 
        声明事务策略
          id是标示符
          transaction-manager 事务管理器
     -->
    <tx:advice id="tx" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 
                告诉spring容器什么样的目标方法采用什么样的事务策略
                 name 用来说明目标方法
                   save*  以save开头的目标方法
                   isolation 隔离属性
                   propagation 传播属性
                        是解决事务嵌套问题的
                   read-only
                        为true:只读事务  只能读
                        为false:读写事务
             -->
            <tx:method name="save*"
                isolation="DEFAULT"
                propagation="REQUIRED"
                read-only="false"/>
        </tx:attributes>
    </tx:advice>
    
    <aop:config>
        <aop:pointcut 
            expression="execution(* com.itheima11.spring.jdbc.transaction.service.impl.*.*(..))" 
            id="perform"/>
        <aop:advisor advice-ref="tx" pointcut-ref="perform"/>
    </aop:config>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,042评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,996评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,674评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,340评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,404评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,749评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,902评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,662评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,110评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,577评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,258评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,848评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,726评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,952评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,271评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,452评论 2 348

推荐阅读更多精彩内容