spring的核心是IOC(控制反转)和AOP(面向切面)
今天先来学习下IOC。IOC另一种说法是依赖注入(DI),它能够通过三种注入方式来将工程中耦合性很高的类进行不完全解耦。
三种注入方式:⑴构造器注入 ⑵接口注入 ⑶setter方法注入!
一般的话都会使用setter方法注入的方式来进行编程;下面来讲解一下spring依赖注入的原理(我的理解)
在java中类与类之间的关系是相互调用的关系,所以如果一个类需要调用另一个类的方法就需要创建出另一个类的对象,通过对象来调用另一个类的方法,比如这样:
一个狗的类,拥有叫和跳两种方法:
package com.ioc.test; import java.util.jar.Attributes.Name; public class Dog { private String name; public void bark(String name ) { System.out.println(name+"叫了一下!"); } public void jump(String name) { System.out.println(name+"跳了一下!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } }而人会命令狗做一些事情,比如让狗叫或者让狗跳之类的,
定义一个person类,拥有让狗叫,让狗跳两种方法。在两种方法中传入Dog的实例对象。
package com.ioc.test; public class Person { private String name; //向方法中传入Dog对象 public void holdDogBark(com.ioc.test.Dog dog){ //调用dog对象的bark方法 并使用传入的dog对象的getName方法获得dog的name属性 //传入bark方法内 dog.bark(dog.getName()); } public void holdDogJump(Dog dog){ dog.jump(dog.getName()); } public String getName() { return name; } public void setName(String name) { this.name = name; } }
写一个拥有main函数的测试类:
在该类中创建两个类的对象并调用Person对象两个方法 ,在方法中传入Dog对象,这样就完成了一次 Person类与Dog类之间的操作。
package com.ioc.test; public class PersonManager { public static void main ( String args[]){ Dog dog =new Dog(); dog.setName("小白"); Dog dog2=new Dog(); dog2.setName("小黑"); Person person=new Person(); person.holdDogBark(dog); person.holdDogJump(dog); person.holdDogBark(dog2); person.holdDogJump(dog2); } }
但是如果这样的话会让代码拥有过高的耦合度,非常的不利于后期的维护与开发。 比如有一天Dog类中会 多一个方法run其中又调用了jump方法
而Person类中新增了一个letDogRun方法并且其中用到了holdDogJump方法 ,就需要将两个类的代码同时 改变。
其实只有这两个类的话还是看不太出来代码耦合度高会带来不便之处,但是如果调用Dog类的类很多的话 而且还有很多使用Person类方法的类,这样你在每个使用过jump和holdDogJump方法的类中都需要进行修 改。这会花费你大量的精力与时间。
而在spring中完成上面的操作会将两个类的关系从相互调用变成依赖注入。而且注入过程中完全不需要你去建立实体类。下面就是步骤
⒈首先导入spring的jar包到所建立的工程中
我这里导入了spring框架的所有jar包如图:
值得注意的是被红线圈住的包 ,我刚开始导入的时候并没有将它导入,之后在测试的时候报了一个错
NoClassDefFoundError,下面是错误信息:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory at org.springframework.context.support.AbstractApplicationContext.<init> (AbstractApplicationContext.java:158) at org.springframework.context.support.AbstractApplicationContext.<init> (AbstractApplicationContext.java:222) at org.springframework.context.support.AbstractRefreshableApplicationContext.<init> (AbstractRefreshableApplicationContext.java:88) at org.springframework.context.support.AbstractRefreshableConfigApplicationContext. <init>(AbstractRefreshableConfigApplicationContext.java:58) at org.springframework.context.support.AbstractXmlApplicationContext.<init> (AbstractXmlApplicationContext.java:61) at org.springframework.context.support.ClassPathXmlApplicationContext.<init> (ClassPathXmlApplicationContext.java:136) at org.springframework.context.support.ClassPathXmlApplicationContext.<init> (ClassPathXmlApplicationContext.java:83) at com.ioc.userioc.test.PersongUseDogTest.main(PersongUseDogTest.java:13) Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 8 more我从网上搜了一下通过 他的博客知道了缺少该包,导入该包后异常果然消失,非常感谢这个博主! 如果想要了解NoClassDefFoundError和ClassNotfoundException的区别的话可以去 这个博客看下。 言归正传, ⒉创建两个接口interface Person和interface Dog,在里面定义需要的方法: Person.java ShortDog.java PersongUseDogTest.java 结果 总结:spring的控制反转就是当一个类需要调用其他类的方法时,通过配置到xml文件中的 一个个bean来生成所需要的对象来注入需要该对象的类的方法中,内部流程完全是spring来 做你只需要使用该类调用方法就可以了。在上面了例子中还用到了一点点的面向切面 (AOP)就是在person再调用holdDogBark方法时注入了ShortDogProxy的实例对象,先 执行了它实现Dog的方法,再将实际的工作类ShortDog类的对象注入到里面,执行 ShortDog对象的bark方法。 全都是在下的一点点见解,如有错误,欢迎指出。