1、Spring是什么?有什么用?spring
Spring的适用环境是这样的,假设如今有一个类port,它将提供一个返回消息的功能,代码以下:spring-mvc
public class port { private weiboMessage weiboMessage; public port(weiboMessage weiboMessage){ this.weiboMessage = weiboMessage; } public String getMessage(){ return weiboMessage.getMessage(); } }
从getMessage方法中咱们能够看到,返回的消息是经过weiboMessage这个对象的完成的,因此这个port类功能的实现,是须要在其内部建立这样一个对象,在这样的场景中port称做被注入对象,weiboMessage称做被依赖对象。mvc
在开发的时候一个类的实现一般须要依赖其余对象,有时候还会出现这样的实现方法(其实大多数时候是这样实现的):app
public String getMessage(){ weiboMessage weiboMessage = new weiboMessage(); return weiboMessage.getMessage(); }
在使用的时候再来建立这个对象,这样的主动的去获取对象实际上是没有必要的,若是依赖的对象过多的话咱们应该考虑转变依赖对象的方式。框架
在Spring中Ioc容器实现的就是改变咱们使用依赖对象的方式,像上面那样被注入对象会直接依赖于被依赖对象,在Ioc中,Ioc将承担提供依赖对象的服务,全部的被注入对象和被依赖对象都将被Ioc所管理,被注入的对象须要什么就跟Ioc要。ssh
2、注入方式ide
依赖注入的方式有三种,构造方法注入、setter方法注入和接口注入,这里就说一下前两种吧,由于接口注入我以为好麻烦==测试
public class port { private weiboMessage weiboMessage; public port(weiboMessage weiboMessage){ this.weiboMessage = weiboMessage; } ...... }
这中场景下Ioc将会扫描被注入对象的构造方法,从而获取它的依赖对象列表,从而进行对象注入。this
这种方法注入方式比较直观,对象构造完成就处于就绪状态,随时均可以使用。spa
public class port { private weiboMessage weiboMessage; public void setWeiboMessage(weiboMessage weiboMessage) { this.weiboMessage = weiboMessage; } ...... }
这样外界能够经过调用setter方法为被注入对象注入所依赖的对象了。这样能够在对象构造完成后再注入对象。
3、使用配置文件的方式实现依赖注入(xml方式)
首先建立一个表示功能的接口:
public interface port { String getMessage(); }
而后是实现该接口的两个类(注入方式不一样):
public class portAImpl implements port { private weiboMessage weiboMessage; public portAImpl(weiboMessage weiboMessage) { this.weiboMessage = weiboMessage; } @Override public String getMessage() { return "A: " + weiboMessage.toString(); } }
public class portBImpl implements port { private weiboMessage weiboMessage; public void setWeiboMessage(weiboMessage weiboMessage) { this.weiboMessage = weiboMessage; } @Override public String getMessage() { return "B: " + weiboMessage.toString(); } }
而后是weiboMessage这个类的实现,
public class weiboMessage { private int id; private String date; private String message; public weiboMessage(int id,String date,String message){ this.id = id; this.date = date; this.message = message; } public long getId() { return id; } public void setId(int id) { this.id = id; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "id: " + id + "date: " + date + "message " + message; } }
这样就实现了一个被依赖类weiboMessage,两个被注入类portAImpl和portBImpl。再而后是配置文件applicationContext.xml的编写:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <bean id="portA" class="com.ssh.respository.impl.portAImpl"> <constructor-arg> <ref bean="weibomessage"/> </constructor-arg> </bean> <bean id="portB" class="com.ssh.respository.impl.portBImpl"> <property name="weiboMessage"> <ref bean="weibomessage"/> </property> </bean> <bean id="weibomessage" class="com.ssh.respository.weiboMessage"> <constructor-arg value="233"/> <constructor-arg value="2018.3.26"/> <constructor-arg value="a message"/> </bean> </beans>
<bean>....</bean>这样的标签就定义了一个类,Ioc中将会记录这个对象的信息,信息包括class类型、是否为抽象对象、构造方法参数及其余属性等。而后就能够根据id向Ioc发出请求就能获得相应的对象。
先看id为weibomessage的中的<constructor-arg>标签表示将使用构造方法进行注入,这里根据构造方法中输入参数的顺序依次进行赋值,id=233,date=2018.3.26,message=a message。
id为portA也一样相似,不过它注入的对象是已经在Ioc容器中已经被注册的类,因此<constructor-arg>标签中的<ref>标签中的bean属性值将是已被注册类的id
前两个都是使用构造方法进行注入的,id为portB的就是使用setter方法进行注册的,使用的是<property>标签,name的值与setter方法的名字有关,bean就是id。
这样就算配置完成了,而后是测试类:
public class test { public static void main(String[] args){ ApplicationContext context = new ClassPathXmlApplicationContext("/META-INF/applicationContext.xml"); port A = (port)context.getBean("portA"); port B = (port)context.getBean("portB"); System.out.println(A.getMessage()); System.out.println(B.getMessage()); } }
运行结果是:
A: id: 233date: 2018.3.26message a message
B: id: 233date: 2018.3.26message a message
最后的使用分为如下两步:
第一步是咱们使用框架 API ClassPathXmlApplicationContext() 来建立应用程序的上下文。这个 API 加载 beans 的配置文件并最终基于所提供的 API,它处理建立并初始化全部的对象,即在配置文件中提到的 beans。
第二步是使用已建立的上下文的 getBean() 方法来得到所需的 bean。这个方法使用 bean 的 ID 返回一个最终能够转换为实际对象的通用对象。一旦有了对象,你就能够使用这个对象调用任何类的方法。
最后给一张此次的demo的项目结构吧,部署这种框架的时候也是常常在项目结构上出错,不过并不就是说我这个项目结构就是正确的,只是能运行而已:
蓝色标注的是我此次用到的,其余的是多余的不必在乎。