zoukankan      html  css  js  c++  java
  • spring工作原理

             对spring原理以前写过类似的博客,地址:点击打开链接

             但是经过一些时间后,尽管天天用着spring,但一提到原理方面,就遗忘了呢?就记得AOP和IOC,但是没有清楚的讲出来呢?

    思考了一下这个问题,总结例如以下。

             1、对于美食的喜爱,以后学习技术的过程中,多和美食相关联,和忘不掉的那些相关联。

             2、总是想着抓住最后一根稻草,却从来没有想过怎样学会游泳。


    IOC(inversion of control)控制反转

             概念:控制权有对象本身转向容器。由容器依据配置文件区创建实例并创建各个实例之间的依赖关系。

             核心:spring封装了抽象工厂模式;bean工厂创建的各个实例称作为bean。

             理解:喜欢吃的东西不一定自己亲自去做。交给食品加工厂去做不是更好吗。spring让一个对象不用创建new了。能够自己主动生产。这就是利用java的反射机制动态创建、调用对象,spring就是在执行时,根xml 是pring配置文件动态创建对象,和调用对象里的方法的。

             spring IOC 应用了单例模式,一次new一个全局对象,也能够在配置文件里进行配置,配置为不使用单例模式。


    AOP(aspect oriented programming)面向切面编程

             1、不使用代理方式

             我们以这个为实例(http://blog.csdn.net/lovesummerforever/article/details/22668947),分别画出类图例如以下所看到的:


             2、代理的两种方式

             静态代理

             针对每一个详细类分别编写代理类。针对一个接口编写一个代理类;


             动态代理

             针对一个方面编程写一个invocationHandler。然后借用JDK反射包中的proxy类为各个接口动态生成对应的代理类。

            

            http://blog.csdn.net/lovesummerforever/article/details/22664647本篇文章有非常好的解释。比方针对调用接口的一些安全性检查,非常多的类的方法都要改动,假设使用静态代理的话,建立代理类并继承真实的类,我们把安全性检查抽象出一个方法,这样每次调用接口方法前,都进行安全性检查,可是这样的方法在代码编译的时候就创建代理类了,而且对原始类的改动,就要更改代理类,这样不符合类的开闭原则(软件设计应该对扩展开放,对改动关闭)。那如何动态的创建这个代理类(执行时)。于是我们能够使用JDK自带的动态代理,在使用这个类的时候创建。


            怎样使用JDK动态代理呢?

            1、实现InvocationHandler接口。

            2、通过Proxy,依据目标来生成代理。

            

            3、invoke方法,该方法中调用详细的切入方法。

            动态代理与静态代理差别

            静态代理:由程序猿创建,再对其编译。在程序执行之前.class文件已经存在了。静态代理:在程序执行时。运用反射的机制动态创建而完毕。无需程序猿手动编写代码,利用jdk的动态代理机制就可以。不仅简化了编程工作,且提高了软件的可扩展性,由于java的反射机制能够生成随意类型的动态代理。


            动态代理使用场景:不同意直接訪问某些类,对訪问要做特殊处理;或者对原始方法进行统一的扩展,比如日志的记录。



             springAOP

             springAOP核心也是动态代理,spring採用三种方式实现代理功能。

    1、java的动态代理方式。2、CGlib方式。3、Aspectj方式。

             默认模式

             spring使用java动态代理和CGlib的混合方式提供服务。即若对象实现了接口则spring自己主动採用java动态代理进行支持。否则则採用CGlib方式进行支持;也能够强制制定使用cglib方式代理,在配置文件里进行配置。

    (http://my.oschina.net/coldlemon/blog/178586)

             比如spring aop控制事务代码例如以下

    	<!--事务相关控制-->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">     
              <property name="dataSource" ref="dataSource"></property>
        </bean>     
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
        	<tx:attributes>
        		<tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="Exception" />
          		<tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="Exception" />  		
    		    <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="Exception" />
    		    <tx:method name="find*" read-only="true"/>
        	</tx:attributes>
        </tx:advice>
        <!--把事务控制在Service层-->
        <aop:config>    
    	    <aop:pointcut id="pc" expression="execution(public * com.msc.biz.service.*.*(..))" /> 
    	    <aop:advisor pointcut-ref="pc" advice-ref="txAdvice" />
        </aop:config>

             通过spring AOP特性来加入日志模块


             日志类:

    import org.apache.log4j.Logger;
    import org.aspectj.lang.JoinPoint;
      
      
    /** 
     * 日志记录,加入、删除、改动方法AOP 
     * @author HotStrong 
     *  
     */  
    public class LogAspect {  
    	private static final Logger logger = Logger.getLogger(LogAspect.class);
              
    	//在类里面写方法,方法名诗能够随意的。此处我用标准的before和after来表示  
        //此处的JoinPoint类能够获取,action全部的相关配置信息和request等内置对象。  
    	 public void before(JoinPoint joinpoint){  
    	 }  
    	 public void after(JoinPoint joinpoint){  
    	 } 
    	  
    //有參并有返回值的方法
    	 public void logArgAndReturn(JoinPoint point, Object returnObj) {
    		 //此方法返回的是一个数组。数组中包含request以及ActionCofig等类对象
    		 logger.debug("运行的方法名为:"+point.getSignature());
    		 Object[] args = point.getArgs();
    		 String arg="";
    	  if (args != null) {
    	      for (Object obj : args) {
    	    	  if(obj != null){
    	    		  arg+=obj.toString()+",";
    	    	  }
    	    	 
    	  }
    	  logger.debug("运行的方法參数为:"+arg);
    	  logger.debug("运行的方法返回值为:"+returnObj);  
         }
      }
    }

             配置切面,切入点,和通知

     <!--针对于service中方法的监控--> 
    	<bean id="logProcess" class="com.xsc.biz.common.LogAspect"></bean> <!--将日志类注入到bean中。-->
    	<aop:config>  
                   <aop:aspect id="b" ref="logProcess"><!--调用日志类-->  
                   <aop:pointcut id="log" expression="execution(* com.xsc.biz.service.*.*(..))"/><!--配置在log包下全部的类在调用之前都会被拦截-->  
                   <!--在log包以下全部的类的全部方法被调用之前都调用MyLog中的before方法-->
                   <aop:before pointcut-ref="log" method="before"/> 
                   <!--在log包以下全部的类的全部方法被调用之后都调用MyLog中的after方法--> 
                   <aop:after pointcut-ref="log" method="after"/>  
      		<aop:after-returning method="logArgAndReturn" returning="returnObj" pointcut-ref="log"/>
                   </aop:aspect>   
        </aop:config>


             这里配置<aop:aspect>是针对什么问题,调用哪个类。

    <aop:pointcut>是日志类方法的切入点,是在业务层。全部方法运行完成切入。<aop:before><aop:after>是通知什么时候运行什么方法<aop:after-returning>是处理结果返回时的操作。运行方法logArgAndReturn。



             有些仓促。有时间一定会清晰的再整理一遍。





  • 相关阅读:
    cityscapes和Mapillary Vistas两种不同分割数据集的label映射
    探究Z-Order
    Java ——对Swing、AWT和SWT的认识 原创
    UOJ-581 NOIP2020 字符串匹配
    UOJ-618 JOISC2021 聚会 2
    Codeforces Round #740 (Div. 1, based on VK Cup 2021
    PipeCAD
    第三次全国国土调查相关信息记录
    统计研究区内Landsat影像数量
    GEE数据导出注意事项
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/6953129.html
Copyright © 2011-2022 走看看