发表于: 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
- http\://www.springframework.org/schema/tx/spring-tx-2.5.xsd=org/springframework/transaction/config/spring-tx-2.5.xsd
- http\://www.springframework.org/schema/tx/spring-tx-3.0.xsd=org/springframework/transaction/config/spring-tx-3.0.xsd
- http\://www.springframework.org/schema/tx/spring-tx-3.1.xsd=org/springframework/transaction/config/spring-tx-3.1.xsd
- 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的配置:
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-shade-plugin</artifactId>
- <version> 1.7.1</version>
- <executions>
- <execution>
- <phase>package</phase>
- <goals>
- <goal>shade</goal>
- </goals>
- <configuration>
- <transformers>
- <transformer
- implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
- <resource>META-INF/spring.handlers</resource>
- </transformer>
- <transformer
- implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
- <resource>META-INF/spring.schemas</resource>
- </transformer>
- <transformer
- implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
- <mainClass>com.chenzhou.test.Main</mainClass>
- </transformer>
- </transformers>
- </configuration>
- </execution>
- </executions>
- </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,线程2s = 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没写完的功能
评论