Spring 学习笔记
Posted atliwen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 学习笔记相关的知识,希望对你有一定的参考价值。
原先的 Spring 学习的时候的笔记 整理了一下 觉得还行 简单实用 共享一下
1 要点记录 2 3 spring Ioc 4 { 5 6 7 1 spring bean 在反射创建对象后 使用的是单例模式! 存在数据安全的问题 8 属性是被共享的! 9 如果该属性有数据,会引起线程安全的问题! 10 <bean id="helloWorid" class="cn.itcast.springTest.HelloWorid" scope="prototype" > </bean> 11 可以通过 XML 配置来设置 spring 默认是 单例的 scope="prototype" 就变成了 多例的了 12 13 2 <bean id="personService" class="com.myapp.core.beanscope.PersonService" scope="singleton" init-method="init" destroy-method="cleanUp"> 14 15 nit-method 是设置 spring 在创建bean节点里面的 对象 时 初始化的时候 调用的方法 16 注: 在构造 或 静态 后面调用 17 destroy-method 是设置 bean 节点创建的对象 在销毁的时候 调用的方法 18 注: 如果是多例 的时候 spring 不负责销毁动作 19 20 21 22 3 spring 容器 (反射出的类对象) 的 三种初始化方法 23 24 3.1 默认的是 调用 无参的构造函数 25 26 3.2 factory-method=“” 需要创建类中的 方法 通过该方法的到返回的类型 27 实例: 28 public class HelloWorldFactory { 29 public static HelloWorld getInstance(){ 30 return new HelloWorld(); 31 } 32 } 33 34 35 4 spring 中 只要声明一个 bean 节点 运行的时候就会创建一个对象 36 37 38 5 spring 在启动的时候 spring 容器配制中的类 就已经创建完成了! 39 40 6 控制容器中的类创建时候 41 lazy-init 这个属性中设置 42 <bean id="helloWorid" class="cn.itcast.springTest.HelloWorid" lazy-init="true" ></bean> 43 在启动spring容器的时候,spring容器配置文件中的类就已经创建完成对象了 44 lazy-init 45 default false 46 true 在context.getBean的时候才要创建对象 47 * 优点 48 如果该bean中有大数据存在,则什么时候context.getBean,什么时候创建对象 49 可以防止数据过早的停留在内存中,做到了懒加载 50 * 缺点 51 如果spring配置文件中,该bean的配置有错误,那么在tomcat容器启动的时候,发现不了 52 false 在启动spring容器的时候创建对象 53 * 优点 54 如果在启动tomcat时要启动spring容器, 55 那么如果spring容器会错误,这个时候tomcat容器不会正常启动 56 * 缺点 57 如果存在大量的数据,会过早的停留在内存中 58 <bean id="helloWorld" class="cn.itcast.spring0909.createobject.when.HelloWorl" lazy-init="true"></bean> 59 <bean id="person" class="cn.itcast.spring0909.createobject.when.Perso" lazy-init="true"></bean> 60 61 62 63 64 总结: 65 spring的IOC : 66 1 IOC :spring容器控制对象的生命周期 ; 前提条件 :在容器中的bean 必须是单例 67 1.1 : 创建 68 1.1.1 : 方式 69 利用默认的构造函数 70 利用静态工厂方法 71 利用实例工厂方法 72 1.1.2 : 时机 73 lazy-init 为"default/false" 当启动 spring 容器的时候 创建bean 74 但是如果bean 是 prototype(多例) 时,特殊。这种情况无效 75 76 ps:在spring启动的时候就会发现错误 ,有肯能照成一些数据长时间的驻留在内存中 77 78 lazy-init 为"true" 当context。getBean时创建 79 bean为多例时,必须用这种方式创建对象 80 81 PS: 不能及时发现错误, 数据会在需要的时候加载 82 83 1.2 : 初始化 84 1.2.1 : 由spring容器调用init 方法, 在构造函数之后执行 85 86 87 1.3 : 销毁 88 1.3.1 : 如果是单利,则必须返回CalssPathXmlApplicationContext该容器,才能执行销毁 89 1.3.2 : 如果是多例,则容器不负责销毁 90 91 } 92 93 spring DI 依赖注入 94 { 95 96 定义: 给属性赋值就是依赖注入 97 98 1.1 利用Set来赋值 99 { 100 <bean id="person" class="cn.spring.di.xml.set.Person"> 101 <!-- 102 property就是代表属性 103 在spring中基本类型(包装类型和String)都可以用value来赋值 104 引用类型用ref赋值 105 --> 106 <property name="pid" value="5"></property> 107 <property name="pname" value="王二"></property> 108 <property name="student"> 109 <ref bean="student"/> 110 </property> 111 <property name="lists"> 112 <list> 113 <value>list1</value> 114 <value>list2</value> 115 <ref bean="student"/> 116 </list> 117 </property> 118 <property name="sets"> 119 <set> 120 <value>set1</value> 121 <value>set2</value> 122 <ref bean="student"/> 123 </set> 124 </property> 125 <property name="map"> 126 <map> 127 <entry key="map1"> 128 <value>map1</value> 129 </entry> 130 <entry key="map2"> 131 <value>map2</value> 132 </entry> 133 <entry key="map3"> 134 <ref bean="student"/> 135 </entry> 136 </map> 137 </property> 138 <property name="properties"> 139 <props> 140 <prop key="prop1"> 141 prop1 142 </prop> 143 </props> 144 </property> 145 </bean> 146 } 147 148 1.2 利用构造函数赋值 149 { 150 <bean id="person" class="cn.spring.di.xml.constructor.Person"> 151 <!-- 152 构造函数的参数 153 index 第几个参数,下标从0开始 154 type 参数的类型 155 ref 如果类型是引用类型,赋值 156 value 如果类型是基本类型,赋值 157 说明: 158 只能指定一个构造函数 159 --> 160 <constructor-arg index="0" type="java.lang.String" value="露露"></constructor-arg> 161 <constructor-arg index="1" ref="student"></constructor-arg> 162 </bean> 163 164 <bean id="student" class="cn.spring.di.xml.constructor.Student"></bean> 165 166 类: 167 public Person(Long pid,String pname){ 168 this.pid = pid; 169 this.pname = pname; 170 } 171 172 public Person(String pname,Student student){ 173 this.pname = pname; 174 this.student = student; 175 } 176 177 } 178 179 180 } 181 182 183 IOC 和DI 做了什么事情? 184 185 * 创建对象 186 * 给对象赋值 187 188 IOC 和DI 的意思 189 190 * 可以在类中引用一个接口,而给接口赋值的工作交给spring容器来做,程序员只需要在配置文件中做一些配置就行。 191 这样在客户端做到了 完全的 面向接口编程 192 193 194 195 196 spring AOP : 197 198 { 199 * AOP 的核心就是动态代理; 200 其实就是 为目标类 方法进行一次包装 , 在方法执行前 和之后 触发其他模块方法执行 201 202 * springAOP的各个概念: 203 204 1. 切面: 205 切面指的就是 对目标类方法包装 时 提前或之后执行的方法的 类对象 206 2. 通知: 207 指得是 对目标类方法包装 时 提前或之后执行的方法 208 3. 切入点: 209 指的是 只有符合切入点,才能把通知和目标方法结合在一起 就是一个对目标方法的一个验证 210 4. 连接点: 211 指的是 客户端调用的方法 也就是具体调用的方法 212 213 * 代理对象的方法=通知+目标方法 214 * aop:做到了代码块的重用 215 216 217 关于SpringAOP的 配置 从spring_aop示例中找寻 218 219 关于切入点表达式 从 spring.xls 表格中找寻 220 221 222 223 springAOP 的原理: 224 225 226 227 * 加载配置文件,启动spring容器 228 * spring容器为bean创建对象 229 * 解析aop的配置,会解析切入点表达式 230 * 看纳入spring管理的那个类和切入点表达式匹配,如果匹配则会为该类创建代理对象 231 * 代理对象的方法体的形成就是目标方法+通知 232 * 客户端在context.getBean时,如果该bean有代理对象,则返回代理对象,如果没有代理对象则返回原来的对象 233 234 235 * 说明: 236 如果目标类实现了接口,则spring容器会采用jdk proxy, 如果目标类没有实现接口,则spring容器会采用 cglibproxy 237 238 239 240 241 PS: 有参数的通知方法: 242 243 通知有 前置 后置 异常 最终 环绕 这些类型 244 245 通长自己写的通知方法是用的是 无参方法, 如果需要获得 连接点 也就是客户端调用方法 的信息的时候 使用有惨方法 246 247 示例: 248 { 249 250 /** 251 * 前置通知 252 * 通过JoinPoint获取连接点的信息 253 */ 254 public void beginTransaction(JoinPoint joinPoint){ 255 joinPoint.getArgs();//获取方法的参数 256 String methodName = joinPoint.getSignature().getName(); 257 System.out.println(methodName); 258 System.out.println("begin transaction"); 259 } 260 /** 261 * 后置通知 ,Object val 是返回值 262 * 注意 在配置文件中 配置的后置通知XML 中 returning=”var“ 263 * 那么 定义方式的时候 返回值名称也得 和 配置文件中相同 264 * 265 * 如果目标方法遇到异常 ,改通知将不执行 266 * 267 */ 268 public void commit(JoinPoint joinPoint,Object val){ 269 List<Person> personList = (List<Person>)val; 270 System.out.println(personList.size()); 271 System.out.println("commit"); 272 } 273 /** 274 * 最终通知 // 在目标方法执行之后 275 * 无论目标方法是否遇到异常 ,都执行 经常做一些关闭资源的动作 276 */ 277 public void finallyMethod(){ 278 System.out.println("finally method"); 279 } 280 281 /** 282 * 异常通知 283 */ 284 public void exceptionMethod(Throwable ex){ 285 System.out.println(ex.getMessage()); 286 } 287 /** 288 * 环绕通知 289 * 能控制目标方法的执行 相当于拦截器方法 290 * @param joinPoint = 客户端调用的方法 291 * @throws Throwable 292 */ 293 public void aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable{ 294 System.out.println("aaaa"); 295 // 获取客户端调用方法的名称 296 String methodName = joinPoint.getSignature().getName(); 297 // 判断是否是 期望的方法 298 if("savePerson".equals(methodName)){ 299 // 是 就让 客户端调用的方法执行 300 joinPoint.proceed();// 301 } 302 // 否 客户端方法 不执行 303 } 304 305 306 } 307 308 PS: 前置通知 和 后置通知 只能在目标方法中 添加内容 ,但是控制不了方法的指向 309 310 重要提示: 通知是通过 配置文件的从上往下 执行的! 311 } 312 313 314 315 316 317 spring 中的 注解器 使用和运行机制 318 319 320 PS: @Resource 这个注解类 是最常用的 321 322 323 324 依赖注入的注解解析器 325 326 { 327 原理 328 329 * 启动spring容器,并且加载配置文件 330 * 会为student和person两个类创建对象 331 * 当解析到<context:annotation-config></context:annotation-config> 332 会启动依赖注入的注解解析器 333 * 会在纳入spring管理的bean的范围内查找看哪些bean的属性上有@Resource注解 334 * 如果@Resource注解的name属性的值为"",则会把注解所在的属性的名称和spring容器中bean的id进行匹配 335 如果匹配成功,则把id对应的对象赋值给该属性,如果匹配不成功,则按照类型进行匹配,如果再匹配不成功,则报错 336 * 如果@Resource注解的name属性的值不为"", 会把name属性的值和spring容器中bean的id做匹配,如果匹配 337 成功,则赋值,如果匹配不成功 ,则直接报错 338 * 说明: 339 * 注解只能用于引用类型 340 * @author Administrator 341 * 342 343 344 实例: 345 { 346 347 <!-- 348 1、导入命名空间 349 xmlns:context="http://www.springframework.org/schema/context" 350 http://www.springframework.org/schema/context 351 http://www.springframework.org/schema/context/spring-context-2.5.xsd 352 2、导入依赖注入的注解解析器 353 <context:annotation-config></context:annotation-config> 354 3、把student和person导入进来 355 --> 356 <context:annotation-config></context:annotation-config> 357 <bean id="student" class="cn.spring.di.annotation.Student"></bean> 358 <bean id="person" class="cn.spring.di.annotation.Person"></bean> 359 360 361 362 public class Person { 363 @Resource(name="student") 364 //@Autowired//按照类型进行匹配 365 //@Qualifier("student") 366 private Student studen; 367 368 } 369 public class Student { 370 public void say(){ 371 System.out.println("student"); 372 } 373 } 374 375 } 376 } 377 378 类扫描的注解解析器 379 { 380 381 原理 382 * 启动spring容器,加载配置文件 383 * spring容器解析到 384 <context:component-scan base-package="cn.spring.scan"></context:component-scan> 385 * * spring容器会在指定的包及子包中查找类上是否有@Component 386 * * 如果@Component注解没有写任何属性 387 * @Component 388 * public class Person{ 389 * 390 * } 391 * == 392 * <bean id="person" class="..Person"> 393 * 如果@Component("aa") 394 * @Component 395 * public class Person{ 396 * 397 * } 398 * == 399 * <bean id="aa" class="..Person"> 400 * * 在纳入spring管理的bean的范围内查找@Resource注解 401 * * 执行@Resource注解的过程 402 * 说明: 403 * xml效率比较高,但是书写比较麻烦 404 * 注解效率比较低,书写比较简单 405 * 不推荐实用 类扫描注解解析器 Spring Ioc 的目的就是解耦 如果控制 还在代码中写死 这种意义就不大 同时也不方便 阅读代码 406 * 407 408 实例 409 { 410 <!-- 411 1、导入命名空间 412 xmlns:context="http://www.springframework.org/schema/context" 413 http://www.springframework.org/schema/context 414 http://www.springframework.org/schema/context/spring-context-2.5.xsd 415 2、启动类扫描的注解解析器 416 3、启动依赖注入的注解解析器 417 --> 418 419 <!-- 420 component就是bean 421 base-package 422 会在base-package的值所在的包及子包下扫描所有的类 423 --> 424 <context:component-scan base-package="cn.spring.scan"></context:component-scan> 425 426 427 428 @Component("perso") 429 public class Person {} 430 @Component 431 public class Student {} 432 433 434 435 436 } 437 438 439 440 441 442 443 } 444 445 使用构造器 来控制 bean 加载的 初始化 和 销毁 方法, 446 447 实例: 448 { 449 450 @PostConstruct // 类构造器之后调用 451 public void init(){ 452 System.out.println("init"); 453 } 454 455 @PreDestroy // 在销毁动作之前调用 456 public void destroy(){ 457 System.out.println("destroy"); 458 } 459 460 } 461 462 463 PS: 如果一个类中有 基本类型 ,并且 基本类型是spring的形式来赋值。 这个时候必须使用XML来赋值,不能使用注解 赋值 464 465 PS: 不推荐使用 类型匹配 也就是 466 { 467 @Resource 468 private Student studenA; 469 这里找的是 bean 的 class 的值 470 471 如果定义多个bean class 的值 相同 那么就会报错 因为不确定是哪一个 bean 472 473 474 475 } 476 477 478 479 spring容器中的继承问题 480 481 1.1.1 默认情况下 即便给是 父类的属性注入了 对应的值 ,但是子类 并不会 的到父类的值 482 483 解决方法: 484 485 parent : 让子类拥有父类属性的值 486 487 <bean id="person" class="cn.springTest.Person" parent="personBase"></bean> 488 489 同样 可以让子类拥有父类的属性 自己赋值 不用写 parent 属性 490 <bean id="student" class="cn.spring.extend.Student"> 491 <property name="name" value="aaaaa"></property> 492 </bean> 493 494 495 496 abstract 497 spring容器不会为该类创建对象 498 499 <bean id="person" class="cn.spring.extend.Person" abstract="true"> 500 <property name="name" value="王二的哥"></property> 501 </bean> 502 503 504 以上是关于Spring 学习笔记的主要内容,如果未能解决你的问题,请参考以下文章