赞
踩
JAVA(强类型语言)
java 跨平台:
跨平台:windox linux 等
通过JVM java虚拟机实现,不同平台对应的jvm
JRE/JDK:
JRE:运行环境,包括JVM和核心类库。 --想运行java语音,只需要安装JRE就可以了。
JDK:java程序开发工具包 包括JRE和开发人员使用工具(javac.exe和java.exe)
–编译:
javac 路径
javac I:\java-study\s1.java
–运行:
路径下:java +文件(不要加后缀)
java s1
所以:
JDK>JRE>JVM
JDK=JRE+开发工具;
JRE=JVM+核心类库;
基础语法:
1.注释:
1. 单行 //
2. 多行/* 注释内容*/
3. 文档注释/** 注释内容 */
2.关键字:
字母全部小写:public static final void 等
3.常量:
一个值是不变的,就是常量;像字符串,整数,小数,字符,boolean null 这些常量
常量在JVM中存放在常量池中,常量池在内存位置:
jdk1.7前:永久代;
jdk1.7 :堆内存中
jdk8移除了永久代并由元空间(metaspace)代替,存放在本地内存(native space)中。并没有对常量池再做变动。即常量池一直在堆中。
4.数据类型:(强类型语言)
计算机存储最小信息单元:最小为 位bit 通常用b。、
计算机种最小的存储单元: 字节byte 通常用B 由8个位组成。–宽带的10M代表b,即下载速度才1.25MB
1.基本数据类型:
1.1整数
byte 1B
short 2B
int 4B --默认类型为int
long 8B
1.2浮点数
float 4B
double 8B --默认类型为double
1.3字符
char 2B --char对应的unicode的对应编码
1.4布尔
boolean 1b
2.引用数据库类型--是由类,接口,数组组成 String 5.变量: 例 int a = 10 ; a就是变量 1.同一个方法不能有重复; 2.定义变量一定要赋值; 3.long l = 10000L; --取消默认 float =1.1f; --不然double 在float中放不下会报错; 6.标识符: 1.数字,字母,_,$组成; 2.不能以数字开头; 3.不能是关键字,且区分大小写; 小驼峰:firstName; 大驼峰:FirstName,Student; 7.类型转换: 1.自动装换:将一个表示范围小的数值放到范围大的变量; double d = 10; --d为10.0; byte<short=char<int<long<float<double 2.强制转换:将一个表示范围大的数值放到范围小的变量(不建议,会有数据丢失) int a = (int)22.88; --a=22; 8.运算符 8.1算术运算符: 8.1.1 + - * / % 注意:1.除法得到的时商,取余得到的余数 2.要想得到小数,除数中有浮点数参与 8.1.2 字符的‘+’:字符在计算机加操作中,对应的数值是底层的数值; int i=2; char j='A'; System.out.println(i+j); --75 (int类型。不同类型加运算,会自动升级为高级的) 8.1.3 字符串的加操作: String+int --为拼接 aaa666 "aaa"+1+1 --aaa11 1+1+"aaa" --2aaa(体现了拼接是从前往后的) 8.2 赋值运算符: =,+=,-=,*=,/=,%= :就是给变量赋值的,但是后面5个扩展的运算符隐含了强制类型转换 注: short s = 10; s = (short) (s+10); --如果结果需要用short类型的s接受,则因为+的10为int,所以需要强转,将int强转为short s+=10; --这就不用,因为+=隐含了强制类型转换(因此推荐这样写法) 8.3自增自减运算符: -- ++ 放在变量前后有差异。 int i = 10 ; i++; 先运算,后加1 i--; 先运算,后减1 ++i; 先加1,后运算 --i; 先减1,后运算 8.4关系运算符: == != > < >= <= 结果是boolean类型 , ==为判断,=为赋值 8.5逻辑运算符: 8.5.1:基本逻辑运算符: & 逻辑与 | 逻辑或 ^ 逻辑异或 -->两边一样为false,不同为true ! 逻辑非 以上可以进行逻辑判断 : (i<2)|(i>4) --返回boolean类型,但是i=3时,false|false --> false 不会短路 8.5.2:短路逻辑运算符: && 与 || 或 8.6三元运算符: 关系表达式?表达式1:表达式2; 关系表达式->true 结果为:表达式1 ; 关系表达式->false 结果为:表达式2 ; em: int max=1>2? 1:2; 9. 数据输入: Scanner使用; java.util.Scanner; Scanner s = new Scanner(System.in); int i = s.nextInt(); -- 输入的是int类型 10.分支语句:
–day2
控制语句:
1.控制选择if else if() switch
1.1 if 多条判断:
if(条件1) {
任务1;
}else if(条件2) {
任务2;
}else {
任务3;
}
1.2 switch
switch(int或者String类型的字面量或者变量){ // String 在jdk7后才能使用
case int或者String类型的字面量或者变量:
java;
…
break;
case int或者String类型的字面量或者变量:
java;
…
break;
case int或者String类型的字面量或者变量:
java;
…
break;
…
default :
java;
…
}
上面是默认写法,case合并写法如下,原理是用case穿透:
switch(i){
case 1: case2 :case 3 :
java;
break;
…
}
2.循环结构for while do…while()
1:for(定义变量 ;条件;变量变化 ){
java;
…
}
2. while(boolean){
java;
…
}
3. do{
java;
}while(boolean);
3.控制循环break continue 3.1 break;中断 for(){ break; --跳出循环,终止循环执行;for循环结束 --但是不会影响外层for循环 } 想要跳出多重循环,可以命名外层循环名称或者加标识位。 3.2 continue: for(..){ if(..){ continue; --跳出当前条件循环,单for仍然继续,只是当前执行结束 } .、.. } 方法: 修饰符列表 返回值类型 方法名(形式参数列表){ //形参是局部变量 --只有它是对象时候,传过来是个地址,才能改变 方法体; } 1.方法内存分配: 数据结构: 栈:先进后出,只有栈顶的元素具有活跃状态,栈针一直指向栈顶元素 堆: 方法区内存:最先有数据,因为方法执行最先把class文件装载到虚拟机中 方法执行时候内存在栈,所以栈的活动最频繁,调用方法就是在栈里分配空间,就是压栈。 2.方法重载:overload 3.方法递归 数组: 声明1: int[] a; --未初始化,未分配空间 @@堆 int[] b=null; --@@栈 int[] c={1,2,3};//只能在声明时使用。 栈内存:大小确认,后进先出,主要是基本类型; 堆内存:大小不确定,存放对象类型的; String[] 在args中,args在栈内,String[]对象在堆中,args中存放的是指向String[]的指针(引用) 声明2: int[] a=new int[3]; --长度为3的整型数组 char[] b = new char[3]; --长度为3的字符数组 int[] c=new int[] {10,20,30}; a=new int[] {10,20,30} --赋值1 b[0]=10; b[1]=10; b[2]=10; --赋值2 int[] a={20,20,10} --声明时初始化 //动态初始化 int[] a1 = new int[3]; a1[0]=0; a1[1]=1; // 静态初始化 int[] a2 = new int[] {1,2,3}; 数组属性:a2.length; --数组长度 数组长度固定,有序且连续,若是为赋值,则该位置默认数字为该类型的默认值;数字类型0,对象为null --多维数组: 二维数组:int[][] a3 = new int[][]{ {1,2},{3,4} }; 声明:int[][] a4 = new int[2][3]; 2*3; --常见算法: 面向对象: 面向对象OOP;面向过程POP; 1.POP强调的时功能行为,OOP强调将功能封装进对象,强调具备了功能的对象。 2.OOP更加强调运用人类的日常思维逻辑采用的思想方法与原则,如抽象,分类,继承,聚合,多态等。 OOP三大特征 1.封装;private 2.继承;override 3.多态;overload Java类成员: 方法:就是函数; 属性:成员变量; 实例化:创建具体对象; 静态的: public static String name = "wuguoqing"; 可以用:类名.属性 ; 直接调用,称为类变量; 代码块: {//代码块 System.out.println("================"); this.name="wang"; } static { //静态块,在类加载时候执行的,早于main方法,只执行一次,因为class只加载一次 System.out.println("static"); } 匿名对象: new Student().read(); 不将声明的对象赋值而调用方法,但只适用一次。 方法重载overload: 同一个类中允许存在同一方法名的方法,只要参数的:个数,参数类型不同即可--通过入参辨别; 方法的可变个数的参数: public void test(String[] detail){}; --将入参写成数组,这样入参就存在动态变化 public void test(String... detail){}; --用java特有的方式,实现可变,detail和数组相同, public void test(int a , String... detail){}; --但是有其他类型的参数,要放在后面 方法参数传递: 栈stack:基本数据类型8种(地址+数据),对象的引用(地址); 堆heap: 所有的对象(包括自己定义的对象和字符串对象)的new object()的内容; 方法区method:所有的class和static 变量; ##--所以java的方法传递,基础类型时,是复制的值传递,方法无法改变调用主方法的参数 但是,传递对象时候(引用对象),传递的时复制的对象,方法修改地址的对应堆的对象 ,所以入参对象地址不变,但是对象的数据发生改变。 包package和引用import: export ->到处为jar类型。通常的jar包; import ->代码中找到jar包的具体位置; 例如:java.lang ->String java.net ->执行网络相关类和接口 java.io ->输入、输出 java.util ->集合,日期等 java.text ->java格式化相关 java.sql ->JDBC java.swt ->图形用户界面GUI 封装隐藏: private --只在本文件本调用 default(不写也行) -- 同一个包内多个java文件都能调用 protected --不仅同一个包,子类也能调用 public --都可以调用 构造方法: 1.不写,默认为有一个空的,new String();什么参数都没有的,但是写了,这个默认的就取消了; 2.类的修饰是什么,构造就是什么修饰,比如内部类,default,那么它的构造就是default(不写) 例如: public class P{ public P(){ } } 3.父类的构造器不能被子类继承。 @@0.static静态块,可以在main之前执行,因为它是类加载时执行,早于mian(但只能执行一次,因为加载只加载一次) 1.new通知jvm创建对象,分配内存,实训化; 数:0; Boolean: false; char : ''; object: null; --第一次初始化:按属性进行缺省初始化; @@1-2:可以进入代码块进行:能进行初始化,但是不能获得参数, 是写死的; 2.进入构造方法:(构造初始化:第二次初始化) 给已经分配内存的变量进行赋值; 3.new完成,赋值给变量: this关键字: 1.当前对象的引用: public calss Person{ private String name ; public Persion(String name){ this.name = name; // 可以用以区分属性和形参 } } 2.this() --这种方式来调用构造,放在其他构造方法中: (1)但是必须放在首行; (2)不许自己调自己(构造方法); JavaBean: 属性一般私有,可以称为实体类。 继承: public class A extends B { A 继承 B 类的属性和方法; } 1.提高代码复用性; 2.实现多态 3.不能为了使用相近属性而继承,狗继承人的性别属性,这样逻辑不通 4.子类不能访问父类私有的,只能访问protected ,public 5.java只支持单继承:不能多继承,所以需要多层继承 方法重新:override: 1.子类重写父类方法,只是重新写方法体 2.子类重写,不能使用比父类更严格的访问权限,如父类是public,子类只能是public super: 用来调用父类的属性和方法(子类之上的所有父类层级) 多态: 1.方法的重载重写; 2.对象的多态性--直接应用在抽象类和接口上 ->声明父类,实现子类;--子类可以看成特殊的父类,那么该变量不能访问子类的属性方法 equals(): 字符串的比较内容 装箱拆箱: 主要应用:基本数据类型和字符串的转换 toString();父类Object的toString()方法就是输出当前对象的内存地址,如果要输出其他信息,需要重写方法; static: 静态的:描述的属性,则是类属性,被所有实例化对象共享,使用时要慎重,因为只要一改,所有类都会变化; 类方法:工具类用的比较多,通过类名.方法名调用。 单例设计模式: 设计模式:解决问题的思考方式; 单例:只要一个实例,实例化对象;(只会new 一次) 使用环境:实例化消耗大量时间资源; 懒汉式: private Single(){} //构造私有化 private static Single single = null; public static Single getInst(){ //只能通过共有的getInst()获取实例 if(single==null){ single = new Single(); } return single; } 饿汉式: private Single(){} //构造私有化 private static Single single = new Single(); public static Single getInst(){ //只能通过共有的getInst()获取实例 return single; } 懒汉饿汉区别就是什么时候new这个对象。 初始化块: {}/static{} --对类的成员初始化,静态的开发用的多些,初始化类的静态一些属性 final: 1.final修饰类,类不能被继承; 2.修饰方法,则不能被子类重写; 3.修饰变量,则只能初始化一次。 即final最终版。 抽象类:abstract class B A extends B 1.需要将抽象类中所有抽象方法全部实现,不然A还是抽象的 2.只能继承一个抽象类; 3.抽象类中,抽象方法可以没有方法体。 4.抽象类不能实例化,只能作父类。 5.不能用abstract 修饰,属性,私有方法,构造器,静态方法,final方法; --因为要实现 模板方法设计模式: 抽象类为模板,子类是实现的不同设计模式; 接口: 实现多重继承效果: public interface A{ } 1.成员变量:public static final修饰的; 2.方法都是public abstract 修饰的; 3.没有构造器; 4.多重继承 5.子类没有实现全部的抽象方法,子类仍是抽象类 public B inplements A ,C...{ } --接口和抽象类的异同; 同:接口是抽象的,抽象类也是抽象的,都不能实例化,只能被继承。 如果一个抽象类,所有属性都是public static final 所有的方法都是public abstract.可以将这个抽象类,申明为接口。 类之间继承是extends,接口之间继承也是extends; 异:抽象类只能单继承,接口可以多继承; 接口中所有属性都是public static final 的,抽象类中可以有它的修饰符; 接口中所有方法都是public abstract 方法,抽象类中方法可以实现的,也不必是public 类之间继承用的extends,类继承接口使用的是:implements; --工厂模式: 将类的声明写到公共方法中。 通过工厂把new对象给隔离,通过产品的接口可以接受不同实际产品的实现类。 --内部类: 1.普通内部类: 2.静态: 和普通一样,其实是一个顶级模板,只不过定义在类里面,可以通过OuterClass.InnerClass 访问; 3.局部: 局部内部类:可以直接访问方法中的局部变量,外部类中的属性 内部类与各部类兼容情况下,通过,外部类类名.this.属性名来区分 4.匿名: 实际上是创建一个零时的没有类名的指定类的子类对象。创建一个新功能的对象,而不再意定义的一个类; 异常: ERROR:系统问题 Exception:代码问题 捕获异常:try catch finally 抛出异常:throw--手动抛出 throws--方法上 集合:java.util 集合中存放的是各个基本类型的引用类型 java集合分为三个大类: Set: 无序,不可重复的集合 List:有序,可重复的集合 Map:具有映射关系的集合 1.Set : HashSet : <-Set接口 <- Collection接口 1.无序 因为存放元素时,会调用hashCode()的方法获取该对象的hashCode值,后根据hashCode值 决定存放位置。 2.不可重复的 当两个元素的equal()方法返回true,但是hashCode不相同,HashSet会存在不同位置, 但依然可以添加成功。 3.线程不安全 4.元素可以是null,但是只能存一个null Set set = new HashSet(); //当没有范型限制时,添加只要是Object类型就行 set.add(Object); //添加 set.romove(1) ; //删除 set.contains("a") //判断是否存在 set.clear(); //清空 set.size(); //集合大小int // 使用迭代器遍历 Iterator it = set.iterator(); while(it.hasNext()){ syso(it.next()) } // 使用foreach遍历 for(Object i : set){ syso(i); } TreeSet : <- NavigableSet接口 <- SortedSet接口 <- Set接口 <- Collection接口 1.可以确保集合元素处于排序状态,支持两种排序方式,自然排序和定制排序,默认情况下 采用的时自然排序。 自然排序: 按照大小从小到大排序,所以类型要一样,不然会异常。 定制排序: 实现Comparator<Object>接口,重写compate方法 方法: add(),remove(),clear().contain(),Iterator迭代器,for()遍历, List集合:ArrayList <- List <-Collection 有序,可重复,通过 get()获取该位置元素 list1.addAll(2,list2); //在list1的第三个位置插入list2所有元素 list.indexOf("a"); "a"在list中第一次出现的位置下标 list.lastIndexOf("a");"a"在list中最后一次出现的位置下标 remove(); 根据索引或者元素删除该元素 list.set(1,"a");将第二个元素改为a list.subList(2,4) ; 根据下标位置截取一段元素,形成新的集合,元素包含2,不包含4 list.size() 容量 Vector:老东西,但是线程安全,ArrayList线程不安全,但是还是不推荐。 Map集合:key:value------key不能重复 HashMap: Map<Integer,Integer> m = new HashMap(); m.put(1,1); //put存储 m.get(1); //get获取 m.remove(1) ; //remove根据key移除 map.size() //长度 map.containsKey(key); map.containsKey(Value); //判断是否包含key或Value 遍历1: Set<Object> key = map.KeySet(); for(...){...} 遍历2: Set<Entry<Integer,Integer>> sets = map.entrySet(); for(Entry<Integer,Integer> set : sets){ syso(set.getKey()+":"+set.getValue()); } HashTable: 方法和HashMap一样,但是是线程安全的,HashMap不安全的。 不能以Null为key,但是HashMap可以。 TreeMap: 支持key的自然排序和定制排序。 Collections类的一些方法: Collections.sort(list); 升序排序 Collections.reverse(list); 顺序反转 Collections.replaceAll("a","aa"); 新值替换 范型: 枚举: 案例: enum Season{ SPRING("春天","春暖花开"), SUMMER("夏天","炎炎夏日"), AUTUMN("秋天","秋高气爽"), WINTER("冬天","寒风凛冽"); private final String name; private final String desc; private Season(String name , String desc){ this.name = name; this.desc = desc; } public void show(){ syso(this.name+":"+this.desc); } } public class Test{ public static void main(String[] args){ Season spring = Season.SPRING; spring.show(); } } // 每次通过Season.SPRING获取的Searson对象相同,类似单例模式。 // 枚举类也可以继承接口 常用的类型: --String: 字面量相同时,instanceof不论有几个变量,对象只有一个; 字面量本身就是一个字符串对象。 new String("str") 存在两个对象,使用new就一定创造了一个新的对象,不论字符串的内容是否相同; 不论是 字面量创建还是new String 创建的对象,其中存储的 都是字符串的final char[]; 当我们为一个变量赋一个新的“字符串”内容时,一定是变量指向了一个新的字符串,而不是原字符串的内容改变了 --常用方法: --StringBuffer:可操控字符串对象;(有序的同步),需要排队使用,单线程 --增删改 --StringBulider:同上,父类继承的类都是一样的,(无序的,同时的同步),多个时间,多个对象可以同时使用他 IO流: File 创建,生成文件/文件夹 File f1 = new File("D:\\TEST\\a.txt"); File f2 = new File("D:/TEST/a.txt"); File f3 = new File("D:\\TEST\\"+"a.txt"); File f4 = new File("D:\\TEST\\"+File.separator+"a.txt"); File f5 = new File("src/day12/test.java"); --相对路径 File类可以操作文件本身,但是不能操作文件内容: getName() --文件名称,或者当前文件夹名称 getPath() --文件路径,路径new file()时候写的路径,是绝对的就是绝对的,是相对的就是相对的 getAbsolutePath() --文件,文件夹的绝对路径 getAbsoluteFile() --返回一个用当前文件绝对路径构建的file对象 getParent() --获取父级路径 f.renameTo(new File("d:/test/test1.java")); //给文件或文件夹重命名 exit(); --文件或者文件夹是否存在 canRead() --是否可读 canRead() --是否可写 isFile() --判断当前的File对象是不是文件 isDirectory() --判断当前的File对象是不是文件夹。目录 lastModified() --文件最后修改时间 length() --返回文件长度 ,多少字节数,文件大小 createNewFile(); --创建文件 delete(); --删除文件,文件夹 mkdirs() --创建多层目录 list() --返回String数组,当前文件夹下的所有文件夹和文件的名称 listFiles() --返回File数组,当前文件下所有文件夹和文件的File对象 删除目录的递归方法: IO流: 输入流input,输出流output: 字节流(inputStream outputStream),字符流(reader writer) 重点: 1.文件的字节输入输出流:FileInputStream , FileOutputStream 单位是byte 文件的字符输入输出流:FileReader , FileWriter 2.缓冲的字节流:BufferedInputStream , BufferedOutputStream 缓冲的字符流:BufferedReader , BufferedWriter 3.InputStreamReader 字节转字符输入流 字节 ——>字符 OutputStreamReader 字符转字节输出流 字节 ——>字符 文件字节流: FileInputStream: FileInputStream in = new FileInputStream("d:/a.txt"); //定义一个byte数组接受输入的byte byte[] b = new byte[10]; int len = 0; // read(byte[]) 返回读到最后一个数据,后一个数据;若是-1则是读取完毕 while((len=in.read(b))!=-1){ syso(new String(b,0,len)); } in.close() ; // 使用后一定要关闭 FileOutputStream: // 指定输出路径,若是不存在则创建文件 FileOutputStream out = new FileOutputStream("D:/b.txt"); byte[] b = "abcd".getByte(); out.write(b); //把数据写到内存中 out.flush(); //把内存中的数据刷到硬盘 out.close(); //关闭流 文件复制方法: 字节流非常通用,因为它使用二进制。 文件字符流: 存放数据的临时组数是char[] 其他都一样: 但是字符流只适合操作为字符文档的文件,入txt; 注意: 当路径下有相同文件是,写入一个文件会覆盖原文件。 当路径下没有文件是,读取会异常。 缓冲的字节流:基于计算机与硬盘间操作,相对较慢,速度受到硬盘读写速度制约,所以缓冲流来绕过限制 BufferedInputStream ; BufferedOutputStream 是对FileInputStream ,FileOutputStream的缓冲 缓冲流是基于内存,FileInputStream是基于硬盘的,速度快75000倍: BufferedInputStream: FileInputStream in = new FileInputStream("d:/a.txt"); // 把文件字节流放到缓冲字节输入流对象 BufferedInputStream input = new BufferedInputStream(in); byte[] b = new byte[10]; int len=0; while((len = input.read(b))!=-1){ syso(new String(b,0,len)); } input.close(); // 关闭按照倒叙关闭 in.close(); BufferedOutputStream: FileOutputStream out = new FileOutputStream("D:/b.txt"); BufferedOutputStream output = new BufferedOutputStream(out); output.write("aaaa".getBytes()); output.flush(); output.close(); out.close(); 将文件a内容读取到文件b: 缓冲的字符流:基于计算机与硬盘间操作,相对较慢,速度受到硬盘读写速度制约,所以缓冲流来绕过限制 BufferedReader ; BufferedWriter 是对FileReader ,FileWriter的缓冲 和上面类似,是char[] 为中间件: 转换流: 字节输入流 -> 字符输入流 FileInputStream in = new FileInputStream("d:/a.txt"); // 设置和读取的编码规则要一致,不然会出现乱码 InputStreamReader reader = new InputStreamReader(in , "GBK"); //传流并定义编码 char[] c = new char[1024]; int len = 0 ; while((len = reader.read(c))!=-1){ syso(new String(c,0,len)); } reader.close(); in.close() 字节输出流 -> 字符输出流 FileOutputStream out = new FileOutputStream("D:/b.txt"); OutputStreamWriter writer = new OutputStreamWriter(out , "UTF-8"); writer.write("你好"); writer.flush(); writer.close(); out.close(); 标准的输入流输出流: System.in ; System.out ; // 创建一个接受键盘输入数据的输入流 InputStreamReader in = new InputStreamReader(System.in); // 把输入流放到缓冲流里: BufferedReader read = new BufferedReader(in); // 假如数据是String类型 String s=read.readLine(); read.close(); in.close(); 对象流: 1.计算机存储是二进制; 2.网络通信也是二进制; 3.就是说要将对象转换成二进制数据流,通过网络进行传输 序列化:Serialize:用ObjectOutputStream类讲一个Java对象写入IO流中 反序列化:Deserialize:从IO流中恢复对象 随机读取流:RandAccess... 从文件某个位置开始读取seek(i) JDBC: java DataBase Connectvity;java 数据库连接 一系列接口的定义,是访问数据库的标准接口;数据库是由不同的厂家提供的,具体的实现是不同的。具体的数据库厂家按照这个接口来实现,这样对不同的数据库操作就统一了。 --API: 主要包含在java.sql和javax.sql包当中 --接口,流程: 0.加载数据库的驱动driver DriverManager类 1.连接到sql; connection接口,连接对象 2.向数据库发送语句(执行语句) statement接口(PreparedStatement子接口,CallableStatement子接口)语句对象; 3.处理返回结果 ResultSet接口,接口集对象; 4.释放连接; em: Driver driver=null; //声明一个driver driver = new OracleDriver(); //导入OracleDriver中的OracleDriver()方法,实现接口 String url="jdbc:oracle:thin:@127.0.0.1:1521/xe"; String user="test"; String password="test"; Connection conn=null; Statement stm=null; ResultSet rst=null; try { DriverManager.registerDriver(driver); //驱动管理,驱动注册 conn=DriverManager.getConnection(url, user, password); //注册完后,传参数 stm=conn.createStatement();//连接对象,创建语句对象 rst=stm.executeQuery("select * from t_kinds"); // rst=stm.getResultSet(); ResultSetMetaData md=rst.getMetaData();//元数据对象:对象的对象.去除数据 int colCount=md.getColumnCount(); 网络编程: 1.首先了解下协议部分: TCP/IP协议组,可分为三个层次:网络层、传输层和应用层。 1.网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。 2.传输层中有TCP协议与UDP协议。 3.应用层有FTP、HTTP、TELNET、SMTP、DNS等协议。 因此,HTTP本身就是一个协议,是从Web服务器传输超文本到本地浏览器的传送协议。 2.HTTP: 建立连接和关闭连接: 三次握手,四次挥手 3.ServerSocket 和 Socket : Socket 类 :socket可以使一个应用从网络中读取和写入数据,不同计算机上的两个应用可以通过连接发送和接受字节流, 当发送消息时,你需要知道对方的ip和端口,在java中,socket指的是java.net.Socket类 以public Socket(String host, int port)为例,host为远程机器名称或ip地址,port为端口号。 若连接本地的Server,其端口号为8080,可以写成如下格式
new Socket(“localhost”, 8080);
一旦成功创建一个Socket类的实例,可以用它来发送和接收字节流,发送时调用getOutputStream方法
获取一个java.io.OutputStream对象,接收远程对象发送来的信息可以调用getInputStream方法来返回一个
java.io.InputStream对象。
ServerSocket类 : ServerSocket负责接收客户连接请求,并生成与客户端连接的Socket。ServerSocket与Socket不同, ServerSocket是等待客户端的请求,一旦获得一个连接请求,就创建一个Socket示例来与客户端进行通信。 ServerSocker构造有多种重载方式: ServerSocket serverSocket=new ServerSocket(8080); ServerSocket serverSocket = new ServerSocket(port,3); 把连接请求队列的长度设为 3。这意味着当队列中有了 3 个连接请求时,如果 Client 再请求 连接,就会被 Server拒绝,因为服务器队列已经满了。我们使用的 serverSocket.accept()方法 总之: 客户端向服务器发送请求可分为以下步骤: 1.创建一个Socket实例 2.利用I/O流与服务器进行通信 3.关闭socket 服务器接收客户端请求步骤: 1.创建一个ServerSocket实例,监听客户端发来的请求。 2.与客户端获取连接后,创建一个Socket实例,利用I/O流与客户端进行通信,完毕后关闭Socket。 4.Url类: 该类用来处理有关URL的内容。对于URL类的创建和使用,下面分别进行介绍。 URL可以分为如下几个部分。protocol://host:port/path?query#fragment protocol(协议)可以是 HTTP、HTTPS、FTP 和 File,port 为端口号,path为文件路径及文件名。 URL url = new URL("http://www.runoob.com/index.html?language=cn#j2se"); System.out.println("URL 为:" + url.toString()); System.out.println("协议为:" + url.getProtocol()); System.out.println("验证信息:" + url.getAuthority()); System.out.println("文件名及请求参数:" + url.getFile()); System.out.println("主机名:" + url.getHost()); System.out.println("路径:" + url.getPath()); System.out.println("端口:" + url.getPort()); System.out.println("默认端口:" + url.getDefaultPort()); System.out.println("请求参数:" + url.getQuery()); System.out.println("定位位置:" + url.getRef()); 也可以用url访问网页,获取html文件,http/https都可以: URL url = new URL("https://www.baidu.com"); try { //通过URL的openStrean方法获取URL对象所表示的自愿字节输入流 InputStream is = url.openStream(); InputStreamReader isr = new InputStreamReader(is,"utf-8"); //为字符输入流添加缓冲 BufferedReader br = new BufferedReader(isr); String data = br.readLine();//读取数据 while (data!=null){//循环读取数据 System.out.println(data);//输出数据 data = br.readLine(); } br.close(); isr.close(); is.close(); 反射机制: 1. 什么是反射机制? 首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码, 比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,JAVA反射机制是 在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属 性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制 2. java反射机制提供了什么功能? 1.在运行时能够判断任意一个对象所属的类 2.运行时构造任意一个类的对象 3.在运行时判断任意一个类所具有的成员变量和方法 4.在运行时调用任一对象的方法 5.在运行时创建新类对象 getCalss();后的一些列操作 线程: --实现方式: 继承Thread类,实现Runnable,Callable 接口。重写run方法,后start(); --守护线程: t.getState(); //获取当前线程装填:RUNNABLE,TERMINATED,NEW,TIMED_WAIT,BLOCKED t.setDaemon(true); //设置为影子线程(守护线程) String name=current.getName(); 线程的名字 --背景线程: t.getState(); //获取当前线程装填:RUNNABLE,TERMINATED,NEW,TIMED_WAIT,BLOCKED t.setDaemon(true); //设置为影子线程(守护线程) --同步方法,一个执行,另一个必须等它执行完才能执行该方法:synchronized --线程状态: (1)新建状态:即单纯地创建一个线程,创建线程有三种方式,在我的博客:线程的创建,可以自行查看! (2)就绪状态:在创建了线程之后,调用Thread类的start()方法来启动一个线程,即表示线程进入就绪状态! (3)运行状态:当线程获得CPU时间,线程才从就绪状态进入到运行状态! (4)阻塞状态:线程进入运行状态后,可能由于多种原因让线程进入阻塞状态,如:调用sleep()方法让线程睡眠, 调用wait()方法让线程等待,调用join()方法、suspend()方法(它现已被弃用!)以及阻塞式IO方法。 (5)死亡状态:run()方法的正常退出就让线程进入到死亡状态,还有当一个异常未被捕获而终止了run()方法的执行 也将进入到死亡状态! --死锁: 定义:死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用, 它们都将无法推进下去。这是一个严重的问题,因为死锁会让你的程序挂起无法完成任务。 死锁的发生必须满足以下四个条件: 互斥条件:一个资源每次只能被一个进程使用。 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。 解决:避免死锁最简单的方法就是阻止循环等待条件,将系统中所有的资源设置标志位、排序, 规定所有的进程申请资源必须以一定的顺序(升序或降序)做操作来避免死锁。 --synchronized:监视器锁; 同步的原因是为了防止同一个账号的混乱; synchronized(this){ 同步方法内容(锁的内容) } 账号加锁;--课后完善 账号优化;--课后完善 --volatile: volatile boolean loop=false; //重新加载后,其他线程调用会使用加载后的数值 --等待与通知: wait :1.释放对象的监视器锁; 2.休眠; --wait要释放监视器锁,而sleep并不释放,其他线程无法再进入; notify :notifyAll()-通知所有的,激活;notify()通知优先级高的那个; --线程池: /*可缓冲的线程池*/ ExecutorService pool1=Executors.newCachedThreadPool(); /*定长的线程池*/ ExecutorService pool2=Executors.newFixedThreadPool(4); /*定时线程池,3代表线程数*/ ScheduledExecutorService pool3=Executors.newScheduledThreadPool(3); /*单线程池*/ ExecutorService pool4=Executors.newSingleThreadExecutor(); for(int i=1;i<=100;i++) { pool4.execute(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName()); } }); } pool4.shutdown(); 日期类型: 1.date: Date设置年月日时等方法是过时的,建议使用Calendar对象操作 Date now=new Date(); --现在时间 Data d=new Date(00,0,1); --创建一个时间 1900年1月1号00:00:00 d=new Date(System.currentTimeMillis());====内部英文版本的日期--内部放long值指定日期对象 int year=d.getYear(); 2.Calendar : Calendar.getInstance()方法,获得对象实例 Calendar.geTime()返回Date类型对象 日期格式化: --SimpleDateFormat:可以new,指定样式; SimpleDateFormat fmt=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss E"); Date now =new Data(); String str=fmt.format(now); --格式完成 Data d=fmt.parse(str); --DateFormat:这个类不能new,是抽象类,但是有些静态方法; getDataInstance(),getDataTime()静态方法和获取实例; 23种设计模式:用于面向对象的设计模式 单例模式: 设计模式:解决问题的思考方式; 单例:只要一个实例,实例化对象;(只会new 一次) 使用环境:实例化消耗大量时间资源; 懒汉式:(用的时候才声明) private Single(){} //构造私有化 private static Single single = null; public static Single getInst(){ //只能通过共有的getInst()获取实例 if(single==null){ single = new Single(); } return single; } 饿汉式:(可能会浪费空间) private Single(){} //构造私有化 private static Single single = new Single(); public static Single getInst(){ //只能通过共有的getInst()获取实例 return single; } 懒汉饿汉区别就是什么时候new这个对象。 缺点1:单线程有用,多线程会有问题,即高并发会有时候不声明,需要进阶(双重检测): --DCL懒汉模式 private Single(){} //构造私有化 private static Single single = null; public static Single getInst(){ //只能通过共有的getInst()获取实例 if(single==null){ synchronized(Single.class){ // 锁住这个类 --阻塞式同步 if(single==null){ single = new Single(); } } } return single; } 缺点2:不是与原子性操作:1.分配内存空间,2.执行构造方法,初始化对象,3.把这个对象指向这个空间 会出现指令重排现象。132顺序会出现,则多线程时会出现指令重排。 为了安全:private volatile static Single single = null; /* volatile就可以说是java虚拟机提供的最轻量级的同步机制.用以声明变量的值可能随时 会别的线程修改,使用volatile修饰的变量会强制将修改的值立即写入主存, 主存中值的更新会使缓存中的值失效(非volatile变量不具备这样的特性, 非volatile变量的值会被缓存,线程A更新了这个值,线程B读取这个变量的值时可 能读到的并不是是线程A更新后的值)。volatile会禁止指令重排。*/ // 原子性,可见性,有序性是并发的三大特征,所谓原子性,就是一个操作要么全部执行,要么都不执行。 炫技时刻:静态内部类实现 --还是不安全的,因为反射机制(只要有反射,都是纸老虎) public class Holder { private Holder() {} public static class InnerClass{ private static final Holder holder = new Holder(); } public static Holder getInstance() { return InnerClass.holder; } } 反射来破坏单例: Constructor<Holder> con = Holder.class.getDeclaredConstructor(null); con.setAccessible(true); //无视私有 Holder holder = con.newInstance(); 反抗: private Single(){ synchronized(Sigle.class){ //此时已经升级为三级检测锁 if(single!=null){ thow RuntimeException("不要试图使用反射破坏异常"); } } } //构造私有化 反射-反抗: Holder holder1 = con.newInstance(); Holder holder2 = con.newInstance(); // 同时用反射创建对象 反抗2: private static boolean qingjiang=false; // 使用红绿灯 private Single(){ synchronized(Sigle.class){ //此时已经升级为三级检测锁 if(qingjiang == false){ qingjiang=true; }else{ thow RuntimeException("不要试图使用反射破坏异常"); } } } //构造私有化 反射-反抗2: Field qinjiang = Holder.class.getDeclaredField("qingjiang"); qinjiang.setAccessible(true); Constructor<Holder> con = Holder.class.getDeclaredConstructor(null); con.setAccessible(true); //无视私有 Holder holder1 = con.newInstance(); qinjiang.set(holder1,false); Holder holder2 = con.newInstance(); 道高一尺魔高一丈,这时候只能通过源码分析: 显示Cannot reflectively create enum objects: public enum EnumSingle { INSTANCE; public EnumSingle getInstance() { return INSTANCE; } } class Test{ public static void main(String[] args) { EnumSingle instance1 = EnumSingle.INSTANCE; EnumSingle instance2 = EnumSingle.INSTANCE; System.out.println(instance1); System.out.println(instance2); } } 枚举class反编译分析: javap -p EnumSingle.class --enmu类型就会被反编译为java文件 也可以使用jad 反编译,显示class extends Enum{} 工厂模式: 1)还没有工厂时代:假如还没有工业革命,如果一个客户要一款宝马车,一般的做法是客户去创建一款宝马车,然后拿来用。 2)简单工厂模式:后来出现工业革命。用户不用去创建宝马车。因为客户有一个工厂来帮他创建宝马.想要什么车,这个工厂就可以建。 比如想要320i系列车。工厂就创建这个系列的车。即工厂可以创建产品。 3)工厂方法模式时代:为了满足客户,宝马车系列越来越多,如320i,523i,30li等系列一个工厂无法创建所有的宝马系列。 于是由单独分出来多个具体的工厂。每个具体工厂创建一种系列。即具体工厂类只能创建一个具体产品。但是宝马工厂还是个抽象。 你需要指定某个具体的工厂才能生产车出来。 4)抽象工厂模式时代:随着客户的要求越来越高,宝马车必须配置空调。于是这个工厂开始生产宝马车和需要的空调。 最终是客户只要对宝马的销售员说:我要523i空调车,销售员就直接给他523i空调车了。而不用自己去创建523i空调车宝马车. 这就是工厂模式。 核心:创建者和调用者分离 1.简单工厂模式:(Simple Factory) 产品类: abstract class BMW { public BMW(){ } } public class BMW320 extends BMW { public BMW320() { System.out.println("制造-->BMW320"); } } public class BMW523 extends BMW{ public BMW523(){ System.out.println("制造-->BMW523"); } 工厂类: public class Factory { public BMW createBMW(int type) { switch (type) { case 320: return new BMW320(); case 523: return new BMW523(); default: break; } return null; } 简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。 它存在的目的很简单:定义一个用于创建对象的接口。 先来看看它的组成: 1) 工厂类角色:这是本模式的核心,含有一定的商业逻辑和判断逻辑,用来创建产品 2) 抽象产品角色:它一般是具体产品继承的父类或者实现的接口。 3) 具体产品角色:工厂类所创建的对象就是此角色的实例。在java中由一个具体类实现。 因为每增加一种新型车,都要在工厂类中增加相应的创建业务逻辑(createBMW(int type)方法需要新增case), 这显然是违背开闭原则的。可想而知对于新产品的加入,工厂类是很被动的。对于这样的工厂类,我们称它为全能类或者上帝类。 我们举的例子是最简单的情况,而在实际应用中,很可能产品是一个多层次的树状结构。由于简单工厂模式中只有一个工厂类来对应这 些产品,所以这可能会把我们的上帝累坏了,也累坏了我们这些程序员。
于是工厂方法模式作为救世主出现了。 工厂类定义成了接口,而每新增的车种类型,就增加该车种类型对应工厂类的实现,这样
工厂的设计就可以扩展了,而不必去修改原来的代码。
2.工厂方法模式:(Factory Method) 工厂方法模式去掉了简单工厂模式中工厂方法的静态属性,使得它可以被子类继承。这样在简单工厂模式里集中在工厂方法上的压 力可以由工厂方法模式里不同的工厂子类来分担。 创建工厂类: interface FactoryBMW { BMW createBMW(); } public class FactoryBMW320 implements FactoryBMW{ @Override public BMW320 createBMW() { return new BMW320(); } } public class FactoryBMW523 implements FactoryBMW { @Override public BMW523 createBMW() { return new BMW523(); } } 工厂方法模式仿佛已经很完美的对对象的创建进行了包装,使得客户程序中仅仅处理抽象产品角色提供的接口,但使得对象的 数量成倍增长。当产品种类非常多时,会出现大量的与之对应的工厂对象,这不是我们所希望的。 3.抽象工厂模式:(Abstract Factory) 产品类: //发动机以及型号 public interface Engine { } public class EngineA extends Engine{ public EngineA(){ System.out.println("制造-->EngineA"); } } public class EngineBextends Engine{ public EngineB(){ System.out.println("制造-->EngineB"); } } //空调以及型号 public interface Aircondition { } public class AirconditionA extends Aircondition{ public AirconditionA(){ System.out.println("制造-->AirconditionA"); } } public class AirconditionB extends Aircondition{ public AirconditionB(){ System.out.println("制造-->AirconditionB"); } } 创建工厂类: //创建工厂的接口 public interface AbstractFactory { //制造发动机 public Engine createEngine(); //制造空调 public Aircondition createAircondition(); } //为宝马320系列生产配件 public class FactoryBMW320 implements AbstractFactory{ @Override public Engine createEngine() { return new EngineA(); } @Override public Aircondition createAircondition() { return new AirconditionA(); } } //宝马523系列 public class FactoryBMW523 implements AbstractFactory { @Override public Engine createEngine() { return new EngineB(); } @Override public Aircondition createAircondition() { return new AirconditionB(); } } 客户: public class Customer { public static void main(String[] args){ //生产宝马320系列配件 FactoryBMW320 factoryBMW320 = new FactoryBMW320(); factoryBMW320.createEngine(); factoryBMW320.createAircondition(); //生产宝马523系列配件 FactoryBMW523 factoryBMW523 = new FactoryBMW523(); factoryBMW320.createEngine(); factoryBMW320.createAircondition(); } } 总结: 无论是简单工厂模式,工厂方法模式,还是抽象工厂模式,他们都属于工厂模式,在形式和特点上也是极为相似的,他们的最终 目的都是为了解耦。在使用时,我们不必去在意这个模式到底工厂方法模式还是抽象工厂模式,因为他们之间的演变常常是令人琢磨 不透的。经常你会发现,明明使用的工厂方法模式,当新需求来临,稍加修改,加入了一个新方法后,由于类中的产品构成了不同等级结 构中的产品族,它就变成抽象工厂模式了;而对于抽象工厂模式,当减少一个方法使的提供的产品不再构成产品族之后,它就演变成了工 厂方法模式。 所以,在使用工厂模式时,只需要关心降低耦合度的目的是否达到了。 建造者模式:创建型模式 实现构建和表示分离,解耦! 原型模式:也是创造者模式--创造对象 克隆技术,以某一对象为原型,创建出新的对象,提升效率。 Object类中提供了一种方法,从内存中拷贝 方式: 1.创建A类,实现Cloneable 接口,重写clone()方法; --调用的是native本地的c++方法 2.创建B类实现克隆,可以先声明一个A类v1,然后克隆v2=v1.clone(); 这时v1和v2的数值相同,但是hashcode不同,所以克隆出来内容是一样的,但是不是一个对象; 3.上面是浅克隆,因为V1中属性对象假如Date类型,V2也指向了Date,改变v1的date v2也会改变,也就是说v1和v2公用Date; 4.深克隆:序列化和反序列化可以实现(IO,但是效率降低),但是也可以改造克隆方法: --前: @Override protected Object clone() throw CloneNotSupportedException{ return super.clone(); } --后: @Override protected Object clone() throw CloneNotSupportedException{ Object o = super.clone(); Video v = (Video) o; v.createTime = (Date) this.createTime.clone(); // 把该对象的属性也克隆 return o; } 适配器模式:--结构型模式(用来松耦合) GUI、SpringBoot用的多 em:电脑和电源中间的适配器 方式: 1.继承,适配器类继承网线; --直接就是无线网卡类似,不用声明网线了; 2.组合,适配器类加网线的类声明为一个属性; --高效的,电脑要先插适配,适配接网线; 桥接模式:--结构型模式 当一个场景中有两个变化的维度例如品牌和类型,便抽象出来 --类似java多平台特点,jdbc绑定不同的数据库 1.品牌通过接口,实现多个品牌的具体类; 2.电脑抽象类,组合品牌,再写出电脑的类型的实体类,通过继承抽象电脑类; 3.测试:声明品牌,再用品牌实现具体电脑类 1.类似多继承方案,但是多继承违背了单一原则,复用差,类的个数也多,所以桥接模式减少子类,降低了管理和维护成本 2、可扩展性,符合开闭原则; 1.增加系统的理解和设计难度; 2.方位有局限性,条件是有两个以上维度; 代理模式:静态,动态,cglib动态代理 ; AOP: --公司代码 3.行为型模式: 例如:观察者模式: 对象之间多对一依赖的一种设计方案,被依赖的对象为如气象站,依赖对象如新浪等网站,气象站通知众多网站变化。 传统设计方案:无法在运行时动态添加第三方,违反ocp原则 观察者方案:不用修改weathdate等气象站类,添加观察者即可,实现ocp原则 JDK中Observable类就是用了观察者模式: public class Observable { private boolean changed = false; private Vector<Observer> obs; public Observable(){obs = new Vector<>();} ... } public interface Observer{ void update(Observable o , Objcet arg); } OOP七大原则: 1.开闭原则:对扩展开放,对修改关闭,独立扩展 2.里氏替换原则,继承父类尽量添加新的方法,而不是改变父类的方法。正方形不是长方形 3.依赖倒置原则:要面向接口编程,不要面向实现编程,降低耦合性; 4.单一职责原则:单一功能原则,一个方法实现一个功能,实现原子性,解耦,提高内聚性 5.接口隔离原则:各个类建立他们需要的专门接口 6.迪米特法则:只与你的直接朋友交谈,不和陌生人说话 --降低耦合,但是会产生一些中介类 7.合成复合原则:尽量先使用组合或者聚合等关联关系来实现,其次再考虑继承关系来实现; 数据结构进阶(二叉树): 为什么要学习:如TreeMap,TreeSet,Linux的虚拟内存管理,数据库系统等; 树的定义:是由n个节点组成的具有层次关系的集合; 特点规则: 每一个根最多两个节点,且左节点<根节点<右节点(二叉排序树); 结构分析: 每一个节点有三部分构成,left|Date|Right 代码实现添加,查找,遍历: E:\code\New-computer\newdemo
–3/15:
spring框架:
–10/21视频:
一站式轻量级开源框架,
以ioc,aop为内核没提供了展示层springMVC 和持久层SpringJDBC 众多企业级应用技术
–IOC:控制反转,后提出DI(注入):让调用类对某一接口实现类的依赖关系由第三方(容器或协作类)注入,
以移除调用者对某一接口实现的依赖。
–构造函数注入
--属性注入
--接口注入
--工厂模式注入
--注解方式注入:(只能注入一个,多余的话只能通过xml文件注入)
java.txt --1471
面试题:
1.Bean的生命周期:
在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,
也就是预设为每一个Bean的别名只能维持一个实例,而不是每次都产生一个新的对象使用Singleton
模式产生单一实例,对单线程的程序说并不会有什么问题,但对于多线程的程序,
就必须注意安全(Thread-safe)的议题,防止多个线程同时存取共享资源所引发的数据不同步问题。
然而在spring中 可以设定每次从BeanFactory或ApplicationContext指定别名并取得Bean时都产生
一个新的实例:例如:
在spring中,singleton属性默认是true,只有设定为false,
则每次指定别名取得的Bean时都会产生一个新的实例
一个Bean从创建到销毁,如果是用BeanFactory来生成,管理Bean的话,
会经历几个执行阶段(如图1.1):
。。。。
在说明前可以思考一下Servlet的生命周期:实例化,初始init,接收请求service,销毁destroy; 1、实例化一个Bean--也就是我们常说的new; 2、按照Spring上下文对实例化的Bean进行配置--也就是IOC注入; 3、如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值 4、如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory(setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,只需在Spring配置文件中配置一个普通的Bean就可以); 5、如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接口,有更多的实现方法); 6、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应用于内存或缓存技术; 7、如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。 8、如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法、; 注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中也可以配置非Singleton,这里我们不做赘述。 9、当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法; 10、最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。 2.Bean的作用域: scope:数值的四种,默认singleton <bean id="..." class="..." scope="singleton"> 1.singleton 单例作用域:如果一个 bean 的作用域被声明为 singleton,那么 Spring IoC 容器将只创建一个该对象的实例,并将其存储在缓存中。每次请求该 bean 时,都会返回该缓存对象。Singleton 作用域是所有 bean 的默认作用域。 2.request 请求作用域:该作用域只在 Spring ApplicationContext 的上下文中有效。如果一个 bean 的作用域被声明为 request,就表示其只在此次请求内有效。 3.session 会议作用域:该作用域只在 Spring ApplicationContext 的上下文中有效。如果一个 bean 的作用域被声明为 session,就表示其只在此次会话(session)内有效。 4.prototype 原型作用域:如果一个 bean 的作用域被声明为 prototype,那么每次请求该 bean 时,Spring IoC 都会返回一个新的实例。 --AOP java.txt --1582 到这里,我们已经全部介绍完Spring AOP。回到开篇的问题,我们拿它做什么? 1.Spring声明式事务管理配置:请参考博主的另一篇文章:分布式系统架构实战 demo:SSM+Dubbo 2.Controller层的参数校验:参考 Spring AOP拦截Controller做参数校验 3.使用 Spring AOP 实现 MySQL 数据库读写分离案例分析 4.在执行方法前,判断是否具有权限 5.对部分函数的调用进行日志记录:监控部分重要函数,若抛出指定的异常,可以以短信或邮件方式通知相关人员。 6.信息过滤,页面转发等等功能
–
springMVC框架
–
spring Cloud:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。