初识Spring

Spring
  • 作为一名伟大的java预备程序猿,怎么可能不学习这个开源的轻量级的控制反转(IOC)和面向切面编程(AOP)的容器框架呢.....

很早之前就听说过,并且稍微了解过.可能当时太年轻被概念绕的云里雾里..最终放弃.

Spring概述
  • Spring其实就是一个工厂,用来创建和管理维护对象的状态和各对象之间的依赖关系.
Spring体系结构

1.Spring Core:工厂,创建对象.维护对象之间的依赖关系
2.Spring AOP:面向切面编程,主要是代理
3.Spring Dao:实现数据库操作.支持jdbc
4.Spring ORM:实现对ORM对象映射关系框架的支持.例如Mybatis/Hibernate
5.Spring Context:Spring上下文模块,针对SPring配置文件
6.Spring WEB:整合WEB应用程序的,例如Struts2
7.Spring MVC:Spring针对MVC模式的实现.

#IOC/DI

讲道理,其实IOC和DI就是一个东西,我却到现在才明白.

  • IOC(控制反转)应用本身不对自己的依赖对象创建及维护,依赖对象的创建和维护由外部容器负责,控制权由应用转移到了外部容器.
  • DI(依赖注入):就是在运行期间,容器自动为里面的依赖对象注入值.

public Class UserBiz(){
 private UserDao userdao=new UserDaoImpl();
//当需要这个对象,就主动去new
//这样是硬编码.以后程序修改麻烦.如果实现了依赖注入的话
就会再外部自动注入实例方法.
//控制反转, 就是UserDao这个对象不由自己管理,由外部容器管理
控制权交给外部了
public Boolean addUserBiz(){   
        userdao.save();
}
}
  • SPring基本使用方法

    1.导入jar包
    2.新建applicationcontext.xml


    < bean class="com.no1.biz.GoodsBIZ" name="GoodsBiz">
    < property name="goodsDao" ref="GoodsDAO">
    < !-- 里面注入了一个属性,有GoodsDao实例方法 -->
    < /property>   

  
  • 3.测试是否注入

ApplicationContext context=new ClassPathXmlApplicationContext("applicationcontext.xml");

GoodsBIZ goodsBIZ=(GoodsBIZ)context.getBean("GoodsBiz");

goodsBIZ.save();

这样就实现了依赖注入,无需像以前一样再去里面new对象.这就是传说中的依赖注入和反转控制. Dao对象交给Spirng容器管理,修改直接修改配置文件即可.

#Aop

面向切面编程:将业务类的实现与日志,事务的执行分离,交由容器来实现.将业务流程中的某些点(如方法的调用)作为切入点,将事务,日志作为切片进行织入.

讲的通俗点就是让程序员更专心的写业务代码,不用关日志和事务.

##代理的设计模式

1.静态代理:用子类代理继承父类(被代理类),重写父类方法,从而可以对父类的插入日志事务相关代码.

2.动态代理:

  • 利用jdk的反射类进行代理
  • 基于CGLIB动态类的方法拦截器进行代理

1.切面(Aspect):
一个关注点的模块化,这个关注点可能会横切多个对象。 在Spring AOP中,切面可以使用基于@Aspect注解的方式来实现。 2.连接点(Joinpoint):
在程序执行过程中某个特定的点,在Spring AOP中,一个连接点总是表示一个方法的执行。
3.通知(Advice):
在切面的某个特定的连接点上执行的动作。其中包括了“around”、“before”和“after”等不同类型的通知。
4.切入点(Pointcut):
匹配连接点的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。

##通知类型:

1.前置通知(@Before ):在某连接点之前执行的通知。
2.后置通知(@AfterReturning ):正常完成后执行的通知。
3.异常通知(@AfterThrowing):在方法抛出异常时的通知。
4.最终通知(@After ):退出的时候执行的通知。
5.环绕通知(@Around):包围连接点的通知。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常。

execution 断言的关键字
* 所有返回类型 com.biz.. 这个包和所有的子包
. 所有类的方法
(..) 所有方法参数

##Aop配置
  <bean id="userManager" class="com.kxind.dao.User"/>  
  <bean id="myHandler" class="com.kxind.aop.MyAdvice" />  
    <aop:config>
            <!--定义切面-->  
        <aop:aspect id="aspect" ref="myHandler"> 
            <!--定义切入点,根据断言匹配要切入的类--> 
            <aop:pointcut id="pointUserMgr" expression="execution(* com.kxind.dao.*.*(..))"/>  
            <!--连接点前-->
            <aop:before method="doBefore"  pointcut-ref="pointUserMgr"/>  
            <!--连接点后-->
            <aop:after method="doAfter"  pointcut-ref="pointUserMgr"/>  
            <!--环绕通知-->
            <aop:around method="doAround"  pointcut-ref="pointUserMgr"/>  
            <!--正常完成后执行的通知-->
            <aop:after-returning method="doReturn"  pointcut-ref="pointUserMgr"/>  
            <!--在方法抛出异常时执行-->
            <aop:after-throwing method="doThrowing" throwing="ex" pointcut-ref="pointUserMgr"/>  

        </aop:aspect>  
    </aop:config>  
##切面类
public class MyAdvice(){

 private void doBefore(JoinPoint joinPoint) {  
        System.out.println("-----doBefore().invoke-----");  
        System.out.println(" 此处意在执行核心业务逻辑前,做一些安全性的判断等等");  
        System.out.println(" 可通过joinPoint来获取所需要的内容");  
        System.out.println("-----End of doBefore()------");  
    }  

    /** 
     * 手动控制调用核心业务逻辑,以及调用前和调用后的处理, 
     *  
     * 注意:当核心业务抛异常后,立即退出,转向After Advice 
     * 执行完毕After Advice,再转到Throwing Advice 
     * @param pjp 
     * @return 
     * @throws Throwable 
     */  
    private Object doAround(ProceedingJoinPoint pjp) throws Throwable {  
        System.out.println("-----doAround().invoke-----");  
        System.out.println(" 此处可以做类似于Before Advice的事情");  

        //调用核心逻辑  
        Object retVal = pjp.proceed();  

        System.out.println(" 此处可以做类似于After Advice的事情");  
        System.out.println("-----End of doAround()------");  
        return retVal;  
    }  

    /** 
     * 核心业务逻辑退出后(包括正常执行结束和异常退出),执行此Advice 
     * @param joinPoint 
     */  
    private void doAfter(JoinPoint joinPoint) {  
        System.out.println("-----doAfter().invoke-----");  
        System.out.println(" 此处意在执行核心业务逻辑之后,做一些日志记录操作等等");  
        System.out.println(" 可通过joinPoint来获取所需要的内容");  
        System.out.println("-----End of doAfter()------");  
    }  

    /** 
     * 核心业务逻辑调用正常退出后,不管是否有返回值,正常退出后,均执行此Advice 
     * @param joinPoint 
     */  
    private void doReturn(JoinPoint joinPoint) {  
        System.out.println("-----doReturn().invoke-----");  
        System.out.println(" 此处可以对返回值做进一步处理");  
        System.out.println(" 可通过joinPoint来获取所需要的内容");  
        System.out.println("-----End of doReturn()------");  
    }  

    /** 
     * 核心业务逻辑调用异常退出后,执行此Advice,处理错误信息 
     * @param joinPoint 
     * @param ex 
     */  
    private void doThrowing(JoinPoint joinPoint,Throwable ex) {  
        System.out.println("-----doThrowing().invoke-----");  
        System.out.println(" 错误信息:"+ex.getMessage());  
        System.out.println(" 此处意在执行核心业务逻辑出错时,捕获异常,并可做一些日志记录操作等等");  
        System.out.println(" 可通过joinPoint来获取所需要的内容");  
        System.out.println("-----End of doThrowing()------");  
    }  
}

这样就完成了对User的Spring AOP,执行user下的任何方法时都会根据不同情况执行advice的方法..还有xml配置方式我就不写了.

kxind

性别:男. 敢于尝试 爱折腾的死宅程序猿. https://github.com/kxinds