笔记之_java整理Spring

proxy-target-class属性:
proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理
Spring事务传播机制(面试题)
概述
当我们调用一个基于Spring的Service接口方法(如UserService#addUser())时,它将运行于Spring管理的事务环境中,Service接口方法可能会在内部调用其它的Service接口方法以共同完成一个完整的业务操作,因此就会产生服务接口方法嵌套调用的情况,Spring通过事务传播行为控制当前的事务如何传播到被嵌套调用的目标服务接口方法中。
事务传播是Spring进行事务管理的重要概念,其重要性怎么强调都不为过。但是事务传播行为也是被误解最多的地方,在本文里,我们将详细分析不同事务传播行为的表现形式,掌握它们之间的区别。
事务传播行为种类
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播:
事务传播行为类型                        说明
PROPAGATION_REQUIRED(默认)        如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS            支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY            使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW        新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED        以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER            以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED            如果当前存在事务,则在嵌套事务内执行(REQUIRES_NEW)。如果当前没有事务,则执行中PROPAGATION_REQUIRED类似的操作。


PROPAGATION_NOT_SUPPORTED
    @Override
    public boolean existsName(String name) { 
        boolean result= this.flinkTypeDao.existsName(name)>0;
        //模拟做插入操作
        FlinkType ft=new FlinkType();
        ft.setTypeName("挂起事务");
        this.flinkTypeDao.insert(ft);
        return result;
    }
<tx:method name="insert*" propagation=" PROPAGATION_NOT_SUPPORTED
" />
以非事务的方式提交,如果存在事务,就将当前事务挂起,才会执行insert()
Spring事务什么时候才能回滚?
    发生 RuntimeException (子类)这种时机,才会发生回滚,否则不会回滚
小结
在Spring声明式事务管理的配置中,事务传播行为是最容易被误解的配置项,原因在于事务传播行为名称(如PROPAGATION_NESTED:嵌套式事务)和代码结构的类似性上(业务类方法嵌套调用另一个业务类方法)。这种误解在很多Spring开发者中广泛存在,本文深入讲解了Spring事务传播行为对业务方法嵌套调用的真实影响,希望能帮助读者化解对事务传播行为的困惑。
请写你常见的异常?
IOException, SqlException, FileNotFoundException,  ClassNotFoundException
NullPointerException,NumberFormatException
,IndexOutOfBoundsException,ClassCastException,
StackOverException,StackOverflowError(递归导致的死循环)
 MappingNotFoundException,DateTimeException ,

struts的通用配置:
<!-- 约定大于配置/admin/Flinktype_list.action -->
   <package name="freemarkerPackage" namespace="/admin" extends="commonPackage" >
       <!-- /admin/Flinktype_list.action -->
       <action name="*_*" class="{1}Action" method="{2}">
           <result name="{2}" type="freemarker">/admin/template/{1}/{2}.ftl</result> 
       </action>
   </package>
    FlinktypeAction.java有个String list()-->return list()
    交给freemarker编译-->模板文件/admin/Flinktype/list.action
默认情况事务传播:
@Override
    public boolean existsName(String name) { 
        boolean result= this.flinkTypeDao.existsName(name)>0;
        //模拟做插入操作
        FlinkType ft=new FlinkType();
        ft.setTypeName("挂起事务");
        this.flinkTypeDao.insert(ft);
        return result;
    }

    <tx:advice id="myAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 对你的哪些方法做哪些事务 -->
            <tx:method name="insert*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="execute*" propagation="REQUIRED" />
            <tx:method name="delete*" propagation="REQUIRED" />

            <!-- 以find,get,其它除上面的外方法,都是只读事务 -->
            <tx:method name="find*" propagation="REQUIRED" read-only="true" />
            <tx:method name="get*" propagation="REQUIRED" read-only="true" />
            <tx:method name="*" propagation="REQUIRED" read-only="true" />
        </tx:attributes>此事务是一个只读事务,insert新增不能成功
要解决这个问题,有两种解决方案
1)、直接更改方法名,
exsitsName-executeExistsName/insertExistsName/updateExistsName等
2)、更改事务传播行为existsName
<tx:method name="existsName" propagation="PROPAGATION_REQUIRES_NEW" read-only="true" />

1、Spring有2个最核心概念
   Spring  IoC(控制反转)  和  Spring AOP(面向切面)
2、spring由哪几个部分组成,每个部份的使用
   由7个部分组成
   1)、Spring AOP  面向切面编程 (在程序运行的过程中,动态地为程序添加额外的功能)
   2)、Spring Core  核心 (管理所有的bean)
   3)、Spring ORM  对第三方的ORM框的支持
   4)、Spring DAO   对数据库和事务的支持和管理
   5)、Spring Context   应用程序上下文
   6)、Spring Web      支持web操作
   7)、Spring Web MVC   自己开的MVC框架
核心容器:
核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
Spring 上下文:
Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP:
通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
Spring DAO:
JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
Spring ORM:
Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
Spring Web 模块:
Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Spring MVC 框架:
MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。
3、Spring IoC
   管理所有的Bean,通过BeanFactory来管理的,它提供了创建类的2种方式:
3.1)、 单态Singleton 是默认的也是最常用的对象模型。
3.2)、原型 模型确保每次检索都会创建单独的对象。
4、Spring  IoC  和  AOP的作用?
IoC  你不再手动的去new 对象,而是让Spring依赖注入对象(@Autowired ,@Resource)
AOP 动态为程序添加额外的功能 (事务)
5、Spring优点 (了解)
低侵入式设计
独立于各种应用服务器
依赖注入特性将组件关系透明化,降低了耦合度
面向切面编程特性允许将通用任务进行集中式处理
与第三方框架的良好整合
6、Spring IoC
      解耦
   将组件对象的控制权从代码本身转移到外部容器
组件化的思想:分离关注点,接口和实现分离
依赖的注入:将组件的构建和使用分开
7、在web运行过程中,除了扫包的方式 和@Resource @Autowired注入还有没有其它方式?
WebApplicationContext webApplicationContext = 
WebApplicationContextUtils.getRequiredWebApplicationContext(
ServletActionContext.getServletContext());
 Object  obj=webApplicationContext .getBean("messagePojo");
控制台中使用
ClassPathXmlApplicationContext cpa=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
      //得到spring管理的所有的对象
      Object  obj=cpa.getBean("messagePojo");
8、Spring管理bean可以有3种形式来注入对象
  1)、set方法
         注入的不是以变量为准,而是以setXXX()方法为准
  2)、构造函数
      2.1)、按构造函数中的参数类型依次注入 
      2.2)、按构造函数中的参数名称注入 
      2.3)、按构造函数中的参数的下标注入
  3)、以接口方式进行注入
9、其它类型注入
<!-- 给数组注入值 -->  
<property name="empName">  
    <list>  
        <value>小明</value>  
        <value>小明小明</value>  
        <value>小明小明小明小明</value>  
    </list>  
</property>  
  
<!-- 给list注入值 list 中可以有相当的对象 -->  
<property name="empList">  
    <list>  
        <ref bean="emp2" />  
        <ref bean="emp1"/>  
        <ref bean="emp1"/>  
        <ref bean="emp1"/>  
        <ref bean="emp1"/>  
        <ref bean="emp1"/>  
        <ref bean="emp1"/>  
    </list>  
</property>  
  
<!-- 给set注入值 set不能有相同的对象 -->  
<property name="empsets">  
    <set>  
        <ref bean="emp1" />  
        <ref bean="emp2"/>  
        <ref bean="emp2"/>  
        <ref bean="emp2"/>  
        <ref bean="emp2"/>  
    </set>  
</property>  
  
<!-- 给map注入值 map只有key不一样,就可以装配value -->  
<property name="empMaps">  
    <map>  
        <entry key="11" value-ref="emp1" />   
        <entry key="22" value-ref="emp2"/>  
        <entry key="22" value-ref="emp1"/>  
    </map>  
</property>  
  
<!-- 给属性集合配置 -->  
<property name="pp">  
    <props>  
        <prop key="pp1">abcd</prop>  
        <prop key="pp2">hello</prop>  
    </props>  
</property>  
</bean>  
  
<bean id="emp1" class="com.hsp.collection.Employee">  
    <property name="name" value="北京"/>  
    <property name="id" value="1"/>  
</bean>  
<bean id="emp2" class="com.hsp.collection.Employee">  
    <property name="name" value="天津"/>  
    <property name="id" value="2"/>  
</bean>  
10、Spring自动注入方式  @AutoWired
set注入和构造注入有时在做配置时比较麻烦。所以框架为了提高开发效率,提供自动装配功能,简化配置。spring框架式默认不支持自动装配的,要想使用自动装配需要修改spring配置文件中<bean>标签的autowire属性。自动装配属性有5个值可选,分别代表不同的含义。 
1、byName
 从Spring环境中获取目标对象时,目标对象中的属性会根据名称在整个Spring环境中查找<bean>标签的id属性值。如果有相同的,那么获取这个对象,实现关联。
 整个Spring环境:表示所有的spring配置文件中查找,那么id不能有重复的。
2、byType
 从Spring环境中获取目标对象时,目标对象中的属性会根据类型在整个spring环境中查找<bean>标签的class属性值。如果有相同的,那么获取这个对象,实现关联。
        缺点:如果存在多个相同类型的bean对象,会出错。
如果属性为单一类型的数据,那么查找到多个关联对象会发生错误。
如果属性为数组或集合(泛型)类型,那么查找到多个关联对象不会发生异常。
3、constructor(3.x以上已不能用)
 使用构造方法完成对象注入,其实也是根据构造方法的参数类型进行对象查找,相当于采用byType的方式。如果没找到则抛出异常
4、autodetect
 自动选择:如果对象没有无参数的构造方法,那么自动选择constructor的自动装配方式进行构造注入。如果对象含有无参数的构造方法,那么自动选择byType的自动装配方式进行setter注入。                      
5、no
默认情况下,不自动装配,通过“ref”attribute手动设定。 
<bean>标签的 autowire 属性,它负责自动装配<bean>标签定义 JavaBean 的属性。这样做可以省去很多配置 JavaBean 属性的标签代码,使代码整洁、美观。但是它也有负面影响,即使用自动装配之后,无法从配置文件中读懂 JavaBean 需要什么属性。自动装配存在很多不正确的装配问题,例如错误装载属性、“byType”属性和“constructor”属性对相同类型参数无法判断等。当然,将自动装配和手动装配混合使用也能解决此问题
Spring引用关联
<bean   id=”名称”    class=”完整类”   scope=”singleton/prototype”>
    <property  name=”完整类中的set方法名变量名”  value=”值” />
    <property  name=”完整类中的set方法名变量名”  ref=”引用SpringBean对象” />
</bean>
10、Spring  注解配置
修饰类用的
  @Component   可以修饰所有类上面,如DaoImpl,ServiceImpl,Controller上面(一般用在Util,POJO)
  @Repository     修饰Dao
      @Service        修饰Service
      @Controller      修饰控制器
如果修用了注解,必须在applicationContext.xml中去配置扫包
<context:component-scan 
base-package="com.wisezone.dao,com.wisezone.service,com.wisezone.controller">
</context:component-scan>
11、Spring  aop  专业名称
1)、连接点(JoinPoint)
         触发点  (类初始化前,类初始化后,  方法调用前,方法调用后, 异常)
2)、切点 (pointCut)
         哪些具体方法  
3)、增强  (advice)
          在方法 基础上,去扩展额外的功能(不修改以前类)
          增强Spring有几个定位接口:
          BeforeAdvice(方法执行前)、  
AfterReturningAdvice(方法返回之后)、
ThrowsAdvice(异常)
4)、目标对象 (Target)
           实际业务逻辑类         
5)、引介 (introduction)
引介是一种特殊的增强,它为类添加一些属性和方法,这样,即使一个业务类原本没有实现某个接口,通过AOP的引介功能,我们可以动态的为该业务添加接口的实现逻辑,让业务类成为这个接口的实现类
6)、织入 (Waving)
织入是将增强添加对目标可具体连接点上的过程,AOP像一台织布机,将目标类、增强或者引介通过AOP这台织布机天衣无缝的编织到一起。根据不同的实现技术,AOP有三种织入的方式:
(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器
(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码
(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术
    Spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入
7)、代理(Proxy)
一个类被AOP织入增强后,就产生出一个结果类,它是融合了原类和增强逻辑的代理类。根据不同的代理方式,代理类即有可能时和原类具有相同接口的类,也可能就是原类的子类,所以我们可以采用调用原类相同的方式调用代理类
8)、切面(Aspect)
切面由切点和增强(引介)组成,它既包括了横切逻辑的定义,也包括了连接点的定义,SpringAOP就是负责实施切面的框架,它将切面所定义的横切逻辑织入到切面所指定的连接点中


9)、Spring支持5种类型的增强:
1.前置增强:org.springframework.aop.BeforeAdvice代表前置增强,因为Spring只支持
方法级的增强,所以MethodBeforeAdvice是目前可的的前置增强,表示在目标方法执行前
实施增强,而BeforeAdvice是为了将来版本扩展需要而定义的;
2.后置增强:org.springframework.aop.AfterReturningAdvice代表后增强,表示在目标
方法执行后实施增强;
3.环绕增强:org.aopalliance.intercept.MethodInterceptor代表环绕增强,表示在目标
方法执行前后实施增强;
4:异常抛出增强:org.springframework.aop.ThrowsAdvice代表抛出异常增强,表示在目
标方法抛出异常后实施增强;
5.引介增强:org.springframework.aop.InteoductionInterceptor代表引介增强,表示在
目标类中添加一些新的方法和属性;
这些增强接口都有一些方法,通过实现这些接口方法,在接口方法中这义横切逻辑,就可以将它们织入到目标类的方法的相应连接点的位置。
12、使用配置进行AOP代理设定
     <bean id="people" class="exp1.ChinesePeople"></bean>
     <!-- 再配一个增强 -->
     <bean id="myAdvice" class="exp1.BeforeAdviceDemo"></bean>
    <!-- 使用Spring代理工厂产生一个代理对象 -->
     <bean id="sayHello" class="org.springframework.aop.framework.ProxyFactoryBean">
           <!-- 生成代理接口 -->
        <property name="proxyInterfaces" value="exp1.SayHello"></property>
        <property name="interceptorNames" value="myAdvice"></property>
        <property name="target" ref="people"></property>
        <!-- 变为子类 -->
        <property name="proxyTargetClass" value="false"></property>
     </bean>
    
<property name="proxyTargetClass" value="true"></property>
生成ChinesePeolple子类
<property name="proxyTargetClass" value="false"></property>
JDK动态代理,完全不是Sayhello这个类相关的东西

13、Spring AOP
execution()是最常用的切点函数,其语法如下图所示:
execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)
execution(* com.xxxx.service..(..) )
通过方法签名定义切点
execution(public  * *(..))
匹配所有目标类的public方法,但是不匹配Samartseller和protected void showGoods()方法。第一个*代表返回值;第二个*代表方法名;而..代表任意入参的方法
execution(* *To(..))
匹配目标类所有以To为后缀的方法。他匹配Naïve Waiter和NaughtyWaiter的greetTo()和serveTo()方法。第一个*代表返回类型,而*To代表任意以To为后缀的方法
通过类定义切点
execution(*com.xxxx.Waiter.*(..))
匹配Waiter接口的所有方法,它匹配NaiveWaiter和NaughtyWaiter类的greetTo()和serveTo方法。第一个*代表返回任意类型,com.xxxx.Waiter.*代表Waiter接口中的所有方法
通过类包定义切点
在类名模式串中,以“.*”表示包下的所有类,而“..*”表示包,子孙包下的所有类
execution(* com.xxxx.*(..))
匹配com.xxxxx包下的所有类的所有方法
execution(* com.xxxx..*(..))
匹配com.xxxx包、子孙包下所有类的所有方法,如com.xxxxx.dao、com.xxxxx.service以及com.xxxxx.user包下的所有类的所有方法都匹配,“..”出现在类名中时,后面必须跟“*”表示包、子孙包下的所有类
14、类加载器classLoader工作机制
类加载器就是寻找类或接口字节码文件进行解析并构造JVM内部对象表示的组件。在Java中,类转载器把一个类装入JVM中,需要经过以下步骤:
1.装载:查找和导入Class文件;
2.链接: 执行校验、准备和解析步骤,其中解析步骤是可以选择的:
a)校验: 检查载入Class文件数据的正确性;
b)准备:给类的静态变量分配存储空间;
c)解析:将符号引用变成直接引用;
3.初始化:对类的静态变量、静态代码块进行初始化工作。
类装载工作是由ClassLoader及其之类负责的,ClassLoader是一个重要的Java运行时系统组件,它负责在运行时查找和装入Class字节文件。JVM在运行时会产生三个ClassLoader:跟装载器、ExtClassLoader(扩展类装载器)和AppClassLoader(系统类装载器)。其中,跟装载器不是ClassLoader的子类,它使用C++编写,因此我们在Java中看不到它,跟装载器负责装载JRE的核心类库,如rt.jar,charsets.jar等。ExtClassLoader和AppClassLoader都是ClassLoader的子类。其中ExtClassLoader负责装载JRE扩展目录ext中的JAR类包;AppClassLoader负责装载ClassPath路径下的类包。
这三个类装载器之间存在父子层级关系,跟装载器是ExtClassLoader的父装载器,ExtClassLoader是AppClassLoader的父装载器。
15、通过AspectJ动态配置AOP
import org.aspectj.lang.JoinPoint;
//花费时间AOP
public class SpeendAspectj {
    private long startTime;
    private long endTime;
    // 开始时候
    public void begin(JoinPoint jp) {
        System.out.println("--Spring AOP监听时间开始了-----");
        this.startTime=System.currentTimeMillis();
    }
    // 方法返回以后
    public void end(JoinPoint jp, Object returnValue) {
        this.endTime=System.currentTimeMillis();
        System.out.println(jp.getTarget() + "中的" + jp.getSignature().getName()
                + "的方法总共花费 了:"+(endTime-startTime)+"毫秒");
    }
}

import org.aspectj.lang.JoinPoint;
public class LogAspectj {
    //开始时候
    public void begin(JoinPoint  jp){
        System.out.println("--Spring AOP切面开始了-----");
        System.out.println(jp.getTarget()+"中的"+jp.getSignature().getName()+"的方法");
        
    }
    //方法返回以后
    public void end(JoinPoint  jp, Object returnValue){
        System.out.println("方法执完了返回的结果是:"+returnValue);
        System.out.println("-----------------------------------------");
    }
}

<!-- aop切面配置 -->
    <aop:config proxy-target-class="true">
        <aop:pointcut expression="execution(* com.wisezone.service..*(..))"
            id="myPointCut" />
        <aop:advisor advice-ref="myAdvice" pointcut-ref="myPointCut" />
        <!-- 监听日志 -->
         <aop:aspect ref="log">
             <aop:before method="begin" pointcut-ref="myPointCut"/>
             <aop:after-returning method="end" returning="returnValue" pointcut-ref="myPointCut"/>
         </aop:aspect>
         <!-- 花费时间 -->
         <aop:aspect ref="speedTime">
             <aop:before method="begin" pointcut="execution(* com.wisezone.controller.admin..*(..))"/>
             <aop:after-returning method="end" returning="returnValue" pointcut="execution(* com.wisezone.controller.admin..*(..))" />
         </aop:aspect>
    </aop:config>

 

posted @ 2017-11-19 16:45  莫轩ASL  阅读(184)  评论(-1编辑  收藏  举报