天天看点

从javaweb入门到spring+mvc框架(一)——spring先来学习spring

由于怕过久了对于配置的一些原理和配置上的细节会忘记,所以记录下来。

在学习完javase和javaweb的servlet部分知识后,就必须进入到框架的学习,框架可以减少很多繁琐重复的工作量,提供更强大的功能。

先来学习spring

什么是IOC

所谓控制反转,就是把对其他对象的实例化和调用,转给spring容器来做。

看下面代码:

public class TestIOC {

    LoginService loginService = new LoginServiceImpl();

    loginService.doLogin("张三","123");

}
           

上面TestIOC类需要调用LoginService类,直接实例化它,这就等于LoginService 的控制在TestIOC手里。

如果使用spring的IOC控制反转,那么代码如下:

public class TestIOC {

    LoginService loginService;

    loginService.doLogin("张三","123");

}
           

这时候实例化过程被省略,因为需要的loginService这个实例是spring容器通过配置bean文件在容器中实例化了,然后注入到LoginService这个接口成为它的实例对象。

所以new LoginServiceImpl()这个实例的创建的控制权就从业务逻辑的类中转移到spring容器中,这就是控制反转的意思。

IOC的好处就是能够面向接口编程,减少类之间的耦合,这样每个类都分模块做自己的事情。同时可以把业务分成很多的模块,然后使用容器来装载这些模块,使得它们共同工作,也方便灵活的添加需要的模块bean和排除不需要的模块bean。

什么是AOP

aop即所谓面向切面编程,意思是把你的程序执行过程从上面和下面切开,同时把需要执行的附加内容插入到这个切面中:

public void 普通方法(){

        System.out.println("我是好人");

    }
           

如上,如果要在System.out.println(“我是好人”)之前加上判断,在之后加上确认,如果没有AOP只能进入源码中修改,就像下面这样:

public void 普通方法(){

        doBeforeMethod();

        System.out.println("我是好人");

        doAfterMethod();

    }
           

但是使用AOP后可以把代码切出两个面,一个是在System.out.println(“我是好人”)之前,一个在之后,然后再在切面的位置添加需要的代码即可,原来的代码不变:

public void 普通方法(){

        System.out.println("我是好人");

    }

    public void useAOP(){

        切面:doBeforeMethod();

        调用那个普通方法的代码...

        切面:doAfterMethod();

    }
           

从上面看到,普通方法本身不需要修改,只需要在AOP中找到切面添加相应方法即可,效果就跟把代码插进去一样。

AOP的原理是使用反射,可以用在拦截器(在执行所有内容之前和之后给你执行下某些代码)。也可以用在数据库的事务管理中,简单原理如下:

一个更新操作,需要开启事务,执行更新,提交和回滚三步:

public boolean update() {

        conn.setAutoCommit(false);
        try{

            conn.execute("更新");

            conn.commit();
        } catch(异常) {
            conn.rollback();
        }
    }
           

使用AOP的切面编程思想,把第一步的conn.setAutoCommit(false)和第三步的conn.commit()+conn.rollback()抽取出来,分别放到执行conn.execute(“更新”)之前和之后的两个切面中,变成了:

public boolean update() {

        conn.execute("更新");

    }

    public boolean useAOP() {
        conn.setAutoCommit(false);
        try{

            调用那个更新方法的代码...

            conn.commit();
        } catch(异常) {
            conn.rollback();
        }
    }
           

调用那个更新方法的代码使用的是反射,我们发现update方法只需要关注业务,事务的开启和回滚已经使用AOP思想配置在容器中了。这样做的好处就是,如果有非常多个数据库更新,插入等操作,事务管理的代码都不用写了,在容器中配置开启就可以。

spring的如何初始化bean

一般是在路径下配置的applicationContext.xml中配置好bean,如下:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                        http://www.springframework.org/schema/context 
                        http://www.springframework.org/schema/context/spring-context-4.3.xsd 
                        http://www.springframework.org/schema/aop 
                        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    //看这个bean:
    <bean id="demoService" class="com.pack.DemoServiceImpl">

    </bean>

</beans>
           

上面我们在applicationContext.xml的中配置了一个,指定这个bean的id为demoService,具体的类为com.pack.DemoServiceImpl,那么,ServletContextListener接口的实现类会在spring容器启动(也就是启动你的project app)的时候把applicationContext.xml中的所有bean初始化,如同上面IOC部分提到的一样,不需要自己new一个类实例出来,容器会帮我们注入bean实例。

到此,有三个疑问没有解决:

1、 spring容器 去哪里 调用ServletContextListener接口的实现类

加载applicationContext.xml配置文件需要注册一个监听器,这个监听器需要实现ServletContextListener接口,其实只要在我们熟悉的web.xml文件中配置好:

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
           

ContextLoaderListener就是ServletContextListener接口的实现类,在spring-web.jar包内,spring容器就是根据web.xml中配置的ContextLoaderListener来加载applicationContext.xml配置文件

2、 ServletContextListener接口的实现类 如何 加载applicationContext.xml

3、 加载之后如何实例化和管理bean

ContextLoaderListener会监听启动WebApplicationContext,WebApplicationContext会有一系列的动作包括获取配置文件applicationContext.xml的内容并且初始化bean等(具体实现不清楚),简单原理大概如下。

String xmlPath = "WEB-INF\\applicationContext.xml";
    //获取配置文件的对象等
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
    //获得实例
    DemoService demoService = (DemoService)applicationContext.getBean("id");
           

继续阅读