一、spring项目启动后的加载流程
1.简单介绍
controller:sturts2框架、springMVC框架【负责请求的转发和视图管理】
service:spring框架【实现业务对象管理】
dao:hiberbate、mybatis【数据对象的持久层】
根据这几个框架组合的流行度,主要介绍SSM框架。
当用户发出请求以后,springMVC进行解析,并调用相应的service,service则调用对象的dao,最后把结果进行渲染返回到页面。
2.上述框架在tomcat中的启动程序
Tomcat是根据web.xml进行来启动的,一个简单的web.xml如下:
<!-- 加载spring容器 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- springmvc的前端控制器 -->
<servlet>
<servlet-name>taotao-manager</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>taotao-manager</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
web.xml加载的过程:
(1)项目在启动时,首先会加载spring容器。首先配置ContextLoaderListener监听器【作用是加载spring的配置文件,自动装配ApplicationContext的配置信息】默认的spring的配置文件位置在WEB-INF下,若果不在那里,则需要配置<context-param>,里面配置要加载的文件所在的路径(classpath表示的是类路径)。配置文件包括dao、service、事物。
service中主要配置扫描包:
<context:component-scan base-package="com.taotao.service"/>
dao中的配置:<1>配置数据源,连接数据库<2>让spring容器管理SqlSessionFactory,以单例存在<3>mapper对象交由spring管理,即配置mapper扫描包
事物中的配置:
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 切面 -->
<aop:config>
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* com.taotao.service.*.*(..))" />
</aop:config>
(2)加载springMVC容器,加载springMVC.xml文件。springMVC.xml中主要配置注解驱动,扫描包以及视图解析器。
<!--配置扫描包 ,自动注册到bean -->
<context:component-scan base-package="com.taotao.controller" />
<mvc:annotation-driven />
<!-- 视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
3.先大致说一下springmvc的原理:
<1>用户向服务器发送请求 ,请求被spring的前端控制器servlet DispatcherServlet捕获
<2>DispatcherServlet对请求的url进行解析,得到资源请求标识符URI,根据URI调用HandlerMapping,找到处理请求的controller
<3>controller调用service业务逻辑处理后,返回ModelAndView
<4>DispatcherServlet查询视图解析器,找到ModelAndView指定的视图
<5>视图负责把结果显示到客户端
二、单例模式
//饿汉模式
class Single{
private static Single s=new Single();
private Single(){}
public static Single getSingle(){
return s;
}
}
三、3个线程T1里输出t1,T2输出t2,T3输出t3,如何保证控制台顺序打印t1,t2,t3
我用的方法是join:
/**
* 关于join
* 比如在当前main中增添一个threadC.join()
* 表示main必须等到线程C执行完毕以后才能执行threadC.join()后面的内容
* @author tt
*
*/
public class TestJoin {
public static void main(String[] args) throws InterruptedException {
ThreadC threadC=new ThreadC();
threadC.start();
//threadC.join();
//System.out.println("执行结束!");
}
}
class ThreadA extends Thread{
public void run() {
// TODO Auto-generated method stub
System.out.println("1");
}
}
class ThreadB extends Thread{
public void run() {
// TODO Auto-generated method stub
ThreadA thread=new ThreadA();
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("2");
}
}
class ThreadC extends Thread{
@Override
public void run() {
// TODO Auto-generated method stub
ThreadB thread=new ThreadB();
thread.start();
try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("3");
}
}
join的其中一个作用便是等待当前调用join的线程执行完以后再执行该线程join后面的的内容。关于join的这部分源码:
如果调用join方法的thread还没有结束,则一直wait中,当线程死掉会自动notify进行唤醒。
四、sychornized和volatile关键字
volatile是轻量级的synchronized。锁提供了两种特性,互斥和可见性。因此在保证多线程读写时数据的一致性,可以使用同步即synchronized关键字和可见性即volatile。
1.volatile
可见性的意思即当一个线程修改了共享变量时,另一个线程也能读取到这个最新的数值。
对于volatile修饰的变量在进行写操作时,处理器不会直接和内存通信,会先写入到缓存中。在这个写入缓存的过程中,用到缓存一致性确保修改的原子性。当缓存回写到内存中时会导致其他处理器对此变量的缓存无效,会重新读取此变量的值。
2.synchronized和volatile的区别
2)volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.
3)volatile仅能实现变量的修改可见性,而synchronized则可以保证变量的修改可见性和原子性.
4)volatile不会造成线程的阻塞,而synchronized可能会造成线程的阻塞.