記事のディレクトリ
springIocは何ですか
IOC(制御の反転)は
制御の反転を意味し、彼がデザインのアイデアで実用的な技術ではないコアアイデアは、プログラム(IOCコンテナ)にコントロールオブジェクトのインスタンスを作成することです。..
IOCコンテナ:
管理すべてのコントロールキーと値の容器構造中に作成された逆オブジェクト(単にとして理解することができる:ハッシュマップ「)
?オブジェクトインスタンスオプションで構築IOCのスプリング(反転制御)
1引数なしのコンストラクタを作成するには
、静的なファクトリを作成する2。クラスコンストラクタ内の静的メソッドは、
工場の3例が設立された:のオブジェクトインスタンス構築する方法
:デモコード
春ioc.xmlプロファイルコンテンツを:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 创建方式1:空参构造创建 -->
<bean id="a" class="com.czy.project.demo6.A"/>
<!--
创建方式2:静态工厂创建
调用A的createBObj方法来创建名为b的对象放入容器
-->
<bean id="b" class="com.czy.project.demo6.A" factory-method="createBObj"/>
<!--
创建方式3:实例工厂创建
调用实例a的createCObj方法来创建名为c的对象放入容器
-->
<bean id="c" factory-bean="a" factory-method="createCObj"/>
</beans>
クラスAコード:
public class A {
public A() {
System.out.println("A 无参构造器被调用了.");
}
public static B createBObj() {
System.out.println("A 的静态方法 createBObj 被调用了.");
return new B();
}
public C createCObj() {
System.out.println("A 的实例方法 createCObj 被调用了.");
return new C();
}
}
コードクラスB:
public class B {
}
クラスCコード:
public class C {
}
スタートアップクラスコード:
public class Main {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-ioc.xml");
A a = (A) context.getBean("a");
B b = (B) context.getBean("b");
C c = (C) context.getBean("c");
}
}
出力:
上記の例を通して、私たちはすでにIOCの概念と例を構築する方法を知っている。次に、我々は彼のコア実装を探ります。
アイデアの手書きspringIoc実現
说明:以下代码需要的xml配置文件以及实体类还是用上边的
春は、あなたは確かにファイルをXML必要があり、確かに内容を読み出し、オブジェクトを受信していると考えることができ、XMLでBeanを構成するオブジェクト指向の考え方を知ることです。そして、
1 XML設定クラスBeanを受信するために作成します。
/**
* 用于接收xml中bean标签的属性
* 没什么东西,就是根据bean标签中的属性来定义的
* Author : czy
*/
public class BeanConfig {
private String id;
private String clazz;
private String factoryMethod;
private String factoryBean;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public String getFactoryMethod() {
return factoryMethod;
}
public void setFactoryMethod(String factoryMethod) {
this.factoryMethod = factoryMethod;
}
public String getFactoryBean() {
return factoryBean;
}
public void setFactoryBean(String factoryBean) {
this.factoryBean = factoryBean;
}
}
春の入口には、新しいClassPathXmlApplicationContext(「xmlファイル名」)ではありません。
我々はXmlApplicationContext(「xmlファイル名」)を使用します。//あなたはOK?- > [OK]
2.クラスXmlApplicationContextを作成します。
/**
* 相当于Springl中ClassPathXmlApplicationContext
* 1、解析xml文件
* 2、获取xml文件所有的节点内容
* 3、利用java反射机制创建实例对象
* 4、将实例对象添加到ioc容器
* czy say :SO EASY
*/
public class XmlApplicationContext {
// xml路径
private String xmlPath;
// 存放bean(也就是ioc的容器)
private static HashMap map = new HashMap();
//存放从xml中解析出来的所有bean
private List<BeanConfig> beanConfigs = new ArrayList<BeanConfig>();
//对外的构造函数
public XmlApplicationContext(String xmlPath) {
this.xmlPath = xmlPath;
try {
//解析xml到beanConfigs
getAllElements();
//初始化ioc容器
init();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读取xml文件所有的节点内容,并放入beanConfigs集合
*/
private void getAllElements() throws Exception {
//1.指定路径加载xml到jvm,形成输入流,xml中的所有内容都在这个流中
InputStream is = XmlApplicationContext.class.getClassLoader().getResourceAsStream(xmlPath);
//2.创建解析对象
SAXReader reader = new SAXReader();
//3.获得文档对象(整个xml文件->将输入流转换成文档对象)
Document document = reader.read(is);
//4.获取根节点,也就是对应spring-ioc.xml中的树干beans
Element rootElement = document.getRootElement();
//5.获取元素迭代器,用于获取所有节点内容
Iterator iterator = rootElement.elementIterator();
while (iterator.hasNext()) {
//用于接收xml中bean的属性值
BeanConfig beanConfig = new BeanConfig();
//获取beans的子节点bean
Element bean = (Element) iterator.next();
// 获取bean的属性迭代器
Iterator beanAttributes = bean.attributeIterator();
while (beanAttributes.hasNext()) {
Attribute attribute = (Attribute) beanAttributes.next();
String attributeName = attribute.getName();//属性名
String attributeData = (String) attribute.getData();//属性值
if ("id".equals(attributeName)) {
beanConfig.setId(attributeData);
} else if ("class".equals(attributeName)) {
beanConfig.setClazz(attributeData);
} else if ("factory-method".equals(attributeName)) {
beanConfig.setFactoryMethod(attributeData);
} else {
beanConfig.setFactoryBean(attributeData);
}
}
//将这条bean的属性值放入beanConfigs集合
beanConfigs.add(beanConfig);
}
}
/**
* 这里初始化ioc容器是关键
* 这里就要利用java的反射机制来创建bean实例
*
* @throws Exception
*/
private void init() throws Exception {
/**
* 这里说一点:
* 看spring-ioc.xml中:bean标签有class属性时就没有factory-bean属性,反之
* 有class属性时,就要判断是空参构造创建还是静态工厂创建,也就是判断有没有factory-method属性
* 有factory-bean时,必然是实例工厂创建-必须有factory-method
* 这点要捋清楚
*/
for (BeanConfig bean : beanConfigs) {
if (null != bean.getClazz()) {
//通过全限定类名拿到Class实例clazz
Class clazz = Class.forName(bean.getClazz());
if (null != bean.getFactoryMethod()) {//静态工厂创建bean实例
//方法名获取method对象
Method method = clazz.getDeclaredMethod(bean.getFactoryMethod());
putBean(bean.getId(), method.invoke(null));
} else {//构造器创建bean实例
putBean(bean.getId(), clazz.newInstance());
}
} else if (null != bean.getFactoryBean()) {//实例工厂创建bean实例
//从容器中拿到实体bean
Object obj = getBean(bean.getFactoryBean());
Method method = obj.getClass().getDeclaredMethod(bean.getFactoryMethod());
putBean(bean.getId(), method.invoke(obj));
} else {
System.out.println("czy不知道在搞什么鬼");
}
}
}
/**
* 添加实例对象到ioc容器
*
* @param id:就是bean中自定义的id
* @param object :就是反射机制创建的实例对象
*/
public void putBean(String id, Object object) {
map.put(id, object);
}
/**
* 通过id获取实例对象
*
* @param id:就是bean中自定义的id
* @return
*/
public Object getBean(String id) {
return map.get(id);
}
}
3.起動クラスを作成します。メインは
、プレゼンテーションの開始など、トップエントリーコードではありません。
public class Main {
public static void main(String[] args) {
XmlApplicationContext context = new XmlApplicationContext("spring-ioc.xml");
A a = (A)context.getBean("a");
B b = (B) context.getBean("b");
C c = (C) context.getBean("c");
}
}
これは、テスト結果をしなければならないでしょう思いやりの人ではありません。
4.テスト
母は、それをテストするために、読者をテストします!私はあなたが非常に興味を持っていると信じています。
5.まとめ
springIocのアイデアは大体このようなものです:
図1に示すように、解析XML文書
2は、すべてのノードがコンテンツのXMLファイル取得
3を、Javaリフレクション機構使用してインスタンスを作成し
4を、容器IOCにインスタンスオブジェクトを追加
しかし、内部のバネがああ百本だけではなく、いくつかの行を達成するために知っています。
ヒント:独自のプロジェクトをビルドする直接ダウンコピーして、より多くの感情を読み取るためのコードを使用することができます。コード内の純粋な手書きのコメントが、かなり詳細な行ずつ読んで感じます。私は確かに初心者を読んだ後のアイデアのIOC春を達成する方法を知っていると確信しています。そしてまた、コンテンツは、XMLを読み出してオブジェクトを受信しているか把握することができます。
最后为了方便大家创建工程:
<dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.8.RELEASE</version> </dependency> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> </dependencies>