前言:
我才做项目没多久,几个项目都是用的spring框架,先开始其实并不清楚spring有什么好的特性,只知道别人那样写的,我也就依葫芦画瓢的写,后来也是想搞清楚为什么spring框架这么流行,才来大致的看了一些博文和例子,才理解一些东西;在一开始的时候在我脑子里spring的特性就是aop和ioc,别人一问spring就说这两个东西,到底干嘛的怎么实现的,不知道,那么用就行了,现在看起来感觉好无知,哈哈哈;所以说本人还是只菜鸟,有什么地方说的不对的海清大神们能够纠正和指导;
正文:
行了,废话不多说,直接入主题,本篇就先讲讲ioc这个特性;按照正常的介绍都会列出缩写的英文过来解释下,我就不解释了,ioc就叫控制反转;其实我知道,大部分人一开始接触都会产生疑问,不知道什么意思,那么我那个东西来对比一下,就会简单明了了: 我先类比下,就拿我这个人来说,在没有ioc的情况下时:当我饿了的时候,我肯定要吃饭,我自家去买东西吃,当我渴了的时候我要自己倒水喝;而有了ioc之后的情况:我差不多就和几个月大的小孩一样,当我饿的时候就会有人主动喂我吃,我渴了的时候有人主动给我水喝; 从上面这个例子的对比,我们是不是能很清晰的看到,ioc的控制翻转是什么意思了吧,就是原本应该是我自己去做的东西,而ioc会主动地给我做,控制权完全到了spring的手上,而且当我自己吃东西的时候我知道要去吃什么,但是用了ioc后,我并不知道我将要吃什么,spring拿什么给你吃,你就吃什么,但是这是能满足你的需求的,这样的话就实现了解耦,的一项之间的依赖性不强了,我不需要关心调用的那个类里面有其他什么东西,反正spring会在我要的时候拿给我; 再来看下下面的代码就会更加清新的看到这个控制反转的好处: A类
<pre name="code" class="java">public class A {
public void getMethod(){
B b = new B();
b.eat();
}
public void getMethod1(){
B b = new B();
b.eat();
}
public void getMethod2(){
B b = new B();
b.eat();
}
public void getMethod3(){
B b = new B();
b.eat();
}
}
B类
public class B {
public String eat(){
return "aaaa";
};
}
从上面的代码片我们不难看的出,上面是在不使用ioc的情况下,A类中的方法调用B类中的eat()方法,需要new一个B对象出来调用;这是一次调用,我们来联想一个场景,如果B中的这个方法在很多类中都被调用了,那是不是每次都要A主动地new一次B对象才能进行调用,这样的话得new多少次;而通过ioc就方便多了,无论你A类中需要调用多少次的不需要你主动地去new多少个B类,只需要把这个B类加入到bean容器中管理,spring会在A需要的时候主动给你new一个B然后调用方法,这样是不是省去了很多new,也方便了;实现ioc的方式有两种,一种是在xml文件中配置bean,那些类是要加入bean中管理的就手动加进去;另外一种就是注解,只要在你申明的那个类上加制定注解就可以了;
看下代码:
A类:
import org.springframework.beans.factory.annotation.Autowired;
public class A {
@Autowired
private B b;
public void getMethod(){
b.eat();
}
public void getMethod1(){
b.eat();
}
public void getMethod2(){
b.eat();
}
public void getMethod3(){
b.eat();
}
}
B类:
public class B {
public String eat(){
return "aaaa";
};
}
好了,现在我们知道了控制反转是什么意思了,那在来看看控制反转是怎么实现的呢;我们有就得认识一个新词,DI:依赖注入;就比如说我上面代码片中的那个在声明B上面的@Autowired注解;要知道注解的的实现过程就得知道java中的一个功能,反射;
反射在我们通常的编码情况下不是经常用到;什么是反射呢,简单来讲,就是有一个类,你只知道类名,里面到底有什么你不知道,然后可以通过一些方法你可以动态获取
这个类中的所有方法和属性,就结束了;是怎么实现的呢,现在我们有个类C,先是根据forName("C的路径")或者是C.getClass()来取到C的实例,假如得到的实例叫c1,然后通过c1.getDeclaredMethods();来获取到所有的方法,返回的是个数组;通过c1.getDeclaredFields();获取到所有属性;
下面来看下这段代码:
首先有个未知的类C:
public class C {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "C [age=" + age + ", name=" + name + ", getAge()=" + getAge()
+ ", getName()=" + getName() + ", getClass()=" + getClass()
+ ", hashCode()=" + hashCode() + ", toString()="
+ super.toString() + "]";
}
}
然后在写个TestC类来取出C类中的属性和方法:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class TestC {
public static void main(String[] args) {
C c = new C();
Class<? extends Object> c1 = c.getClass();//取得class对象
Method[] method=c1.getDeclaredMethods();//获取对象中的方法
for(Method m : method){
System.out.println("C中的方法有:"+m.toString());
}
Field[] field=c1.getDeclaredFields();
for(Field f : field){
System.out.println("C中的属性有:"+f.toString());
}
}
}
下面是打印出的结果:
C中的方法有:public java.lang.String com.yoho.controller.C.toString()
C中的方法有:public java.lang.String com.yoho.controller.C.getName()
C中的方法有:public void com.yoho.controller.C.setName(java.lang.String)
C中的方法有:public int com.yoho.controller.C.getAge()
C中的方法有:public void com.yoho.controller.C.setAge(int)
C中的属性有:private int com.yoho.controller.C.age
C中的属性有:private java.lang.String com.yoho.controller.C.name
这样是不是就能直观的看出来了,C中的两个属性和set,get,tostring方法都被打出来了;
行了,反射讲清楚后,那注解就很容易理解了,上面那个@Autowried注解就是类似这样实现的,通过取到注解可以取到类名,或者是类对象类型,这边插个题外话,一般实现装箱的注解@Autowried和@Resource两个都可以,前者是按类型,后者是按名称;好了回归正题,通过取到类名后,就通过反射把这个类中的所有方法都取出来,当然肯定不是像我上面打印出来,而是通过加入到spring的bean容器中管理,然后在有需要用的时候spring就会自动给你提供;