发表于: 2019-11-18 22:55:04

1 982


任务一打包部署到服务器 

java服务中整合了spring,在IDE里本地启动时没问题,但是部署到局域网linux服务器上时解析spring applicationContext.xml报错,具体报错信息如下:

org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/context]  关于这个问题,纠结了我大半天时间,网上的资料也是众说纷纭,有的说是spring版本不统一、有些说是缺少对应的spring依赖的。不过这些原因都被逐一排除了。

功夫不负有心人,在仔细地对比和排查原因之后,发现了问题的所在,在我的jar包下的META-INF目录下,有两个跟spring相关的文件:spring.handlers、spring.schemas,打开这两个文件一看,里面都只包含了spring-tx的配置spring.handlers:http\://www.springframework.org/schema/tx=org.springframework.transaction.config.TxNamespaceHandler  http\://www.springframework.org/schema/tx/spring-tx-2.0.xsd=org/springframework/transaction/config/spring-tx-2.0.xsd  

  1. http\://www.springframework.org/schema/tx/spring-tx-2.5.xsd=org/springframework/transaction/config/spring-tx-2.5.xsd  
  2. http\://www.springframework.org/schema/tx/spring-tx-3.0.xsd=org/springframework/transaction/config/spring-tx-3.0.xsd  
  3. http\://www.springframework.org/schema/tx/spring-tx-3.1.xsd=org/springframework/transaction/config/spring-tx-3.1.xsd  
  4. http\://www.springframework.org/schema/tx/spring-tx.xsd=org/springframework/transaction/config/spring-tx-3.1.xsd 

里面并没有spring-context的schema和handler配置,所以会报错!

那么问题的根源是什么呢,在stackoverflow上找到了答案:http://stackoverflow.com/questions/1937767/spring-3-0-unable-to-locate-spring-namespacehandler-for-xml-schema-namespace

原配置文件

由于没有配置META-INF/spring.handlers和META-INF/spring.schemas所以如果工程中依赖了Spring的多个依赖,在打包时后面的会把前面的覆盖,使得这两个文件中永远只保存最后一个spring依赖的schema和handler。

解决方法就是在里面加上META-INF/spring.handlers和META-INF/spring.schemas的配置:

  1. <plugin>  
  2.     <groupId>org.apache.maven.plugins</groupId>  
  3.     <artifactId>maven-shade-plugin</artifactId>  
  4.     <version> 1.7.1</version>  
  5.     <executions>  
  6.         <execution>  
  7.             <phase>package</phase>  
  8.             <goals>  
  9.                 <goal>shade</goal>  
  10.             </goals>  
  11.             <configuration>  
  12.                 <transformers>  
  13.                     <transformer  
  14.                         implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
  15.                         <resource>META-INF/spring.handlers</resource>  
  16.                     </transformer>  
  17.                     <transformer  
  18.                         implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">  
  19.                         <resource>META-INF/spring.schemas</resource>  
  20.                     </transformer>  
  21.                     <transformer  
  22.                         implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">  
  23.                         <mainClass>com.chenzhou.test.Main</mainClass>  
  24.                     </transformer>  
  25.                 </transformers>  
  26.             </configuration>  
  27.         </execution>  
  28.     </executions>  
  29. </plugin>  

这段配置意思是把spring.handlers和spring.schemas文件以append方式加入到构建的jar包中。修改完后,再次打包,此时就会把工程依赖的所有的spring依赖的schema和handler都加载到spring.handlers和spring.schemas里面。加载applicationContext.xml时就不会报错了。

https://www.iteye.com/blog/chenzhou123520-1706242使用maven插件对java工程进行打包)

spring IOC 深入理解:

Spring IOC容器主要有继承体系底层的BeanFactory、高层的ApplicationContext和WebApplicationContext

Bean有自己的生命周期

容器启动原理:Spring应用的IOC容器通过tomcat的Servlet或Listener监听启动加载;Spring MVC的容器由DispatchServlet作为入口加载;Spring容器是Spring MVC容器的父容器

容器加载Bean原理:

BeanDefinitionReader读取Resource所指向的配置文件资源,然后解析配置文件。配置文件中每一个解析成一个BeanDefinition对象,并保存到BeanDefinitionRegistry中;

容器扫描BeanDefinitionRegistry中的BeanDefinition;调用InstantiationStrategy进行Bean实例化的工作;使用BeanWrapper完成Bean属性的设置工作;

单例Bean缓存池:Spring 在 DefaultSingletonBeanRegistry 类中提供了一个用于缓存单实例 Bean 的缓存器,它是一个用 HashMap 实现的缓存器,单实例的 Bean 以 beanName 为键保存在这个HashMap 中。

-------------------------------------基础复习-------------------------------------------------------------------

多线程(单例设计模式)
* 单例设计模式:保证类在内存中只有一个对象。
* 如何保证类在内存中只有一个对象呢?
* (1)控制类的创建,不让其他类来创建本类的对象。private
* (2)在本类中定义一个本类的对象。Singleton s;
* (3)提供公共的访问方式。  public static Singleton getInstance(){return s}
* 单例写法两种:
* (1)饿汉式 开发用这种方式。
//饿汉式
class Singleton {
//1,私有构造函数
private Singleton(){}
//2,创建本类对象
private static Singleton s = new Singleton();
//3,对外提供公共的访问方法
public static Singleton getInstance() {
return s;
}
public static void print() {
System.out.println("11111111111");
}
}
* (2)懒汉式 
//懒汉式,单例的延迟加载模式
class Singleton {
//1,私有构造函数
private Singleton(){}
//2,声明一个本类的引用
private static Singleton s;
//3,对外提供公共的访问方法
public static Singleton getInstance() {
if(s == null)
//线程1,线程2
s = new Singleton();
return s;
}
public static void print() {
System.out.println("11111111111");
}
}
* (3)第三种格式
class Singleton {
private Singleton() {}
public static final Singleton s = new Singleton();//final是最终的意思,被final修饰的变量不可以被更改
}
DEMO:

public class Demo1_Singleton {

/**

* @param args

* * 单例设计模式:保证类在内存中只有一个对象。

*/

public static void main(String[] args) {

/*Singleton s1 = new Singleton();

Singleton s1 = Singleton.s; //成员变量被私有,不能通过类名.调用

Singleton.s = null;

Singleton s2 = Singleton.s;

System.out.println(s1 == s2);*/

Singleton s1 = Singleton.getInstance();

Singleton s2 = Singleton.getInstance();

System.out.println(s1 == s2);

}

}

/*

 * 饿汉式

 */

class Singleton {

//1,私有构造方法,其他类不能访问该构造方法了

private Singleton(){}

//2,创建本类对象

private static Singleton s = new Singleton();

//3,对外提供公共的访问方法

public static Singleton getInstance() { //获取实例

return s;

}

}

/*

* 饿汉式和懒汉式的区别

* 1,饿汉式是空间换时间,懒汉式是时间换空间

* 2,在多线程访问时,饿汉式不会创建多个对象,而懒汉式有可能会创建多个对象

*/

public static void main(String[] args) {

Singleton s1 = Singleton.getInstance();

Singleton s2 = Singleton.getInstance();

System.out.println(s1 == s2);

}

}

/*

 * 懒汉式,单例的延迟加载模式

 */

class Singleton {

//1,私有构造方法,其他类不能访问该构造方法了

private Singleton(){}

//2,声明一个引用

private static Singleton s ;

//3,对外提供公共的访问方法

public static Singleton getInstance() { //获取实例

if(s == null) {

//线程1等待,线程2等待

s = new Singleton();

}

return s;

}

多线程(Timer类)(计时器)

public class Demo3_Timer {

/**

* @param args

* @throws InterruptedException 

*/

public static void main(String[] args) throws InterruptedException {

Timer t = new Timer();

//在指定时间安排指定任务

//第一个参数,是安排的任务,第二个参数是执行的时间,第三个参数是过多长时间再重复执行

t.schedule(new MyTimerTask(), new Date(188, 6, 1, 14, 22, 50),3000);

while(true) {

Thread.sleep(1000);

System.out.println(new Date());

}

}

}

class MyTimerTask extends TimerTask {

@Override

public void run() {

System.out.println("起床背英语单词");

}

}

多线程(两个线程间的通信)
* 1.什么时候需要通信
* 多个线程并发执行时, 在默认情况下CPU是随机切换线程的
* 如果我们希望他们有规律的执行, 就可以使用通信, 例如每个线程执行一次打印
* 2.怎么通信
* 如果希望线程等待, 就调用wait()
* 如果希望唤醒等待的线程, 就调用notify();
* 这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用
多线程(三个或三个以上间的线程通信)
* 多个线程通信的问题
* notify()方法是随机唤醒一个线程
* notifyAll()方法是唤醒所有线程
* JDK5之前无法唤醒指定的一个线程
* 如果多个线程之间通信, 需要使用notifyAll()通知所有线程, 用while来反复判断条件
/*1,在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法
 * 2,为什么wait方法和notify方法定义在Object这类中?
 *     因为锁对象可以是任意对象,Object是所有的类的基类,所以wait方法和notify方法需要定义在Object这个类中
 * 3,sleep方法和wait方法的区别?
 * a,sleep方法必须传入参数,参数就是时间,时间到了自动醒来
 *   wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待
 * b,sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡
 *     wait方法在同步函数或者同步代码块中,释放锁

JDK1.5的新特性互斥锁)
* 1.同步
* 使用ReentrantLock类的lock()和unlock()方法进行同步
* 2.通信
* 使用ReentrantLock类的newCondition()方法可以获取Condition对象
* 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法
* 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了


_设计模式(适配器设计模式)
* a.什么是适配器
* 在使用监听器的时候, 需要定义一个类事件监听器接口.
* 通常接口中有多个方法, 而程序中不一定所有的都用到, 但又必须重写, 这很繁琐.
* 适配器简化了这些操作, 我们定义监听器时只要继承适配器, 然后重写需要的方法即可.
* b.适配器原理
* 适配器就是一个类, 实现了监听器接口, 所有抽象方法都重写了, 但是方法全是空的.
* 适配器类需要定义成抽象的,因为创建该类对象,调用空方法是没有意义的
* 目的就是为了简化程序员的操作, 定义监听器时继承适配器, 只重写需要的方法就可以了.
明天的计划 任务一总结 深度思考过完 补充DEMO没写完的功能



返回列表 返回列表
评论

    分享到