标签:两种 tutorials space [] clean xmla tar bean gis
1 // 创建应用程序的上下文 2 ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); 3 // 获取bean对象,注意参数是bean的id 4 HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); 5 // 调用bean对象的方法 6 obj.getMessage();
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <beans xmlns="http://www.springframework.org/schema/beans" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 7 8 <bean id="helloWorld" class="com.tutorialspoint.HelloWorld"> 9 <property name="message" value="Hello World!"/> 10 </bean> 11 12 </beans>
两种不同类型的容器:
// 加载beans.xml文件,创建并初始化所有对象 XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("Beans.xml"));
1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <beans 4 默认命名空间,没有空间名,用于spring bean的定义 5 xmlns="http://www.springframework.org/schema/beans" 6 xsi标准命名空间,用于为每个文档中的命名空间指定相应的Schema样式文件 7 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 8 xsi:schemaLocation="http://www.springframework.org/schema/beans 9 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 10 11 <bean id="..." class="..."> 12 <!-- collaborators and configuration for this bean go here --> 13 </bean> 14 15 <bean id="..." class="..." lazy-init="true"> 16 <!-- collaborators and configuration for this bean go here --> 17 </bean> 18 19 <bean id="..." class="..." init-method="..."> 20 <!-- collaborators and configuration for this bean go here --> 21 </bean> 22 23 <bean id="..." class="..." destroy-method="..."> 24 <!-- collaborators and configuration for this bean go here --> 25 </bean> 26 27 </beans>
Bean的定义——Bean的初始化——Bean的使用——Bean的销毁
作用:调用初始化方法前后对 Bean 进行额外的处理
1 // HelloWorld.java (Spring Bean) 2 package com.tutorialspoint; 3 public class HelloWorld { 4 private String message; 5 public void setMessage(String message){ 6 this.message = message; 7 } 8 public void getMessage(){ 9 System.out.println("Your Message : " + message); 10 } 11 public void init(){ 12 System.out.println("Bean is going through init."); 13 } 14 public void destroy(){ 15 System.out.println("Bean will destroy now."); 16 } 17 } 18 19 // InitHelloWorld.java 初始化方法前后执行的逻辑 20 package com.tutorialspoint; 21 import org.springframework.beans.factory.config.BeanPostProcessor; 22 import org.springframework.beans.BeansException; 23 public class InitHelloWorld implements BeanPostProcessor { 24 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 25 System.out.println("BeforeInitialization : " + beanName); 26 return bean; // you can return any other object as well 27 } 28 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 29 System.out.println("AfterInitialization : " + beanName); 30 return bean; // you can return any other object as well 31 } 32 } 33 34 // beans.xml 35 <?xml version="1.0" encoding="UTF-8"?> 36 37 <beans xmlns="http://www.springframework.org/schema/beans" 38 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 39 xsi:schemaLocation="http://www.springframework.org/schema/beans 40 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 41 42 <bean id="helloWorld" class="com.tutorialspoint.HelloWorld" 43 init-method="init" destroy-method="destroy"> 44 <property name="message" value="Hello World!"/> 45 </bean> 46 47 <bean class="com.tutorialspoint.InitHelloWorld" /> 48 49 </beans>
注入前的代码:
1 public class TextEditor { 2 private SpellChecker spellChecker; 3 public TextEditor() { 4 spellChecker = new SpellChecker(); 5 } 6 }
控制反转后(依赖注入后):
1 public class TextEditor { 2 private SpellChecker spellChecker; 3 public TextEditor(SpellChecker spellChecker) { 4 this.spellChecker = spellChecker; 5 } 6 }
实质是将被注入对象(SpellChecker)在注入之前实现,在实例化TextEditor时,将SpellChecker作为一个工具提供给TextEditor。
这个过程spring框架来控制。bean对象间的依赖关系委托到spring框架中。直白说new对象不放在TextEditor中了,而是交给spring框架了。
两种注入方式:
1 // TextEditor.java 2 package com.tutorialspoint; 3 public class TextEditor { 4 private SpellChecker spellChecker; 5 6 public void setSpellChecker(SpellChecker spellChecker) { 7 System.out.println("Inside setSpellChecker." ); 8 this.spellChecker = spellChecker; 9 } 10 11 public SpellChecker getSpellChecker() { 12 return spellChecker; 13 } 14 public void spellCheck() { 15 spellChecker.checkSpelling(); 16 } 17 } 18 19 // SpellChecker.java 20 package com.tutorialspoint; 21 public class SpellChecker { 22 public SpellChecker(){ 23 System.out.println("Inside SpellChecker constructor." ); 24 } 25 public void checkSpelling() { 26 System.out.println("Inside checkSpelling." ); 27 } 28 } 29 30 // MainApp.java 31 package com.tutorialspoint; 32 import org.springframework.context.ApplicationContext; 33 import org.springframework.context.support.ClassPathXmlApplicationContext; 34 public class MainApp { 35 public static void main(String[] args) { 36 ApplicationContext context = 37 new ClassPathXmlApplicationContext("Beans.xml"); 38 TextEditor te = (TextEditor) context.getBean("textEditor"); 39 te.spellCheck(); 40 } 41 } 42 43 // beans.xml 44 <?xml version="1.0" encoding="UTF-8"?> 45 46 <beans xmlns="http://www.springframework.org/schema/beans" 47 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 48 xsi:schemaLocation="http://www.springframework.org/schema/beans 49 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 50 51 <bean id="textEditor" class="com.tutorialspoint.TextEditor"> 52 <property name="spellChecker" ref="spellChecker"/> 53 </bean> 54 55 <bean id="spellChecker" class="com.tutorialspoint.SpellChecker"> 56 </bean> 57 58 </beans>
用于set函数
1 // 使用p-namespace前的beans.xml 2 <?xml version="1.0" encoding="UTF-8"?> 3 4 <beans xmlns="http://www.springframework.org/schema/beans" 5 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 6 xsi:schemaLocation="http://www.springframework.org/schema/beans 7 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 8 9 <bean id="john-classic" class="com.example.Person"> 10 <property name="name" value="John Doe"/> 11 <property name="spouse" ref="jane"/> 12 </bean> 13 14 <bean name="jane" class="com.example.Person"> 15 <property name="name" value="John Doe"/> 16 </bean> 17 18 </beans> 19 20 // 使用p-namespace后的beans.xml 21 <?xml version="1.0" encoding="UTF-8"?> 22 23 <beans xmlns="http://www.springframework.org/schema/beans" 24 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 25 xmlns:p="http://www.springframework.org/schema/p" 26 xsi:schemaLocation="http://www.springframework.org/schema/beans 27 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> 28 29 <bean id="john-classic" class="com.example.Person" 30 p:name="John Doe" 31 p:spouse-ref="jane"/> 32 </bean> 33 34 <bean name="jane" class="com.example.Person" 35 p:name="John Doe"/> 36 </bean> 37 38 </beans>
1 // set方法注入 2 <bean id="outerBean" class="..."> 3 <property name="target"> 4 <bean id="innerBean" class="..."/> 5 </property> 6 </bean>
“后者”的属性是集合形式。唯一不同是beans.xml中<property>的设置
<lsit> | 值可重复 |
<set> | 值不可重复 |
<map> | key-value对,key与value类型任意 |
<props> | key-value对,key与value类型必须为字符串 |
1 // JavaCollection.java (spring bean) 2 package com.tutorialspoint; 3 import java.util.*; 4 public class JavaCollection { 5 List addressList; 6 Set addressSet; 7 Map addressMap; 8 Properties addressProp; 9 10 // 属性的get和set方法 11 ······ 12 } 13 14 // beans.xml 15 <bean id="javaCollection" class="com.tutorialspoint.JavaCollection"> 16 17 <property name="addressList"> 18 <list> 19 <value>INDIA</value> 20 <value>Pakistan</value> 21 <value>USA</value> 22 <value>USA</value> 23 </list> 24 </property> 25 26 <property name="addressSet"> 27 <set> 28 <value>INDIA</value> 29 <value>Pakistan</value> 30 <value>USA</value> 31 <value>USA</value> 32 </set> 33 </property> 34 35 <property name="addressMap"> 36 <map> 37 <entry key="1" value="INDIA"/> 38 <entry key="2" value="Pakistan"/> 39 <entry key="3" value="USA"/> 40 <entry key="4" value="USA"/> 41 </map> 42 </property> 43 44 <property name="addressProp"> 45 <props> 46 <prop key="one">INDIA</prop> 47 <prop key="two">Pakistan</prop> 48 <prop key="three">USA</prop> 49 <prop key="four">USA</prop> 50 </props> 51 </property> 52 53 </bean>
1 <bean id="..." class="..."> 2 3 <!-- Passing bean reference for java.util.List --> 4 <property name="addressList"> 5 <list> 6 <ref bean="address1"/> 7 <ref bean="address2"/> 8 <value>Pakistan</value> 9 </list> 10 </property> 11 12 <!-- Passing bean reference for java.util.Set --> 13 <property name="addressSet"> 14 <set> 15 <ref bean="address1"/> 16 <ref bean="address2"/> 17 <value>Pakistan</value> 18 </set> 19 </property> 20 21 <!-- Passing bean reference for java.util.Map --> 22 <property name="addressMap"> 23 <map> 24 <entry key="one" value="INDIA"/> 25 <entry key ="two" value-ref="address1"/> 26 <entry key ="three" value-ref="address2"/> 27 </map> 28 </property> 29 30 </bean>
1 // 注入空字符串 等价于exampleBean.setEmail("") 2 <bean id="..." class="exampleBean"> 3 <property name="email" value=""/> 4 </bean> 5 6 // 注入null 等价于exampleBean.setEmail(null) 7 <bean id="..." class="exampleBean"> 8 <property name="email"><null/></property> 9 </bean>
依赖注入有两种方式1. 构造函数 2. set函数。这两种方式都需要在beans.xml中配置<constructor-arg><property>标签。
自动装配的意思是不需要这两个标签,由spring框架完成bean之间关系的协作。
自动装配模式由<bean>的autowire指定
byName | 必须有对象属性的set方法,若发现对象属性则自动装配,否则报错。其他属性由<property>指定 |
byType |
必须有对象属性的set方法,有就自动装配,否则报错其他属性由<property>指定 |
constructor | 对象属性不用在<bean>中配置,构造函数中其他的参数需要用<constructor-arg>来配置 |
autodetect | 首先尝试constructor,若不执行则使用byType |
byName与byType中正因为有除了对象属性的其他属性,才会用<property>标签,正因为有此标签,才一定要有set方法。
没有除了对象属性的其他属性,可以没有set方法,因此也没有<property>。
因此byName与byType是用于set方法的自动装配,constructor是构造方法的自动装配
另外:在beans.xml中配置bean时若没有为任何属性赋值,则容器会调用该bean的无参构造函数,虽然指定了byName或者byType
也就是说在<bean>中指定的<constructor-arg>的个数,决定了容器会调用哪个构造函数。
被此注解修饰的set方法的属性,必须在<bean>中被指定,否则 BeanInitializationException 异常
1 package com.tutorialspoint; 2 import org.springframework.beans.factory.annotation.Required; 3 public class Student { 4 private Integer age; 5 private String name; 6 @Required 7 public void setAge(Integer age) { 8 this.age = age; 9 } 10 public Integer getAge() { 11 return age; 12 } 13 @Required 14 public void setName(String name) { 15 this.name = name; 16 } 17 public String getName() { 18 return name; 19 } 20 }
// 属性age与name必须在<bean>中被指定
autowired就是自动装配的意思
1 // 不用使用<constructor-arg><property>来为参数赋值 2.1 2.2 2.3配置都是如此 2 <bean id="textEditor" class="com.tutorialspoint.TextEditor"> 3 </bean> 4 5 <bean id="spellChecker" class="com.tutorialspoint.SpellChecker"> 6 </bean>
自动装配set方法中的对象属性(采用byType自动连接)
消除<property>元素
1 package com.tutorialspoint; 2 import org.springframework.beans.factory.annotation.Autowired; 3 public class TextEditor { 4 private SpellChecker spellChecker; 5 @Autowired 6 public void setSpellChecker( SpellChecker spellChecker ){ 7 this.spellChecker = spellChecker; 8 } 9 public SpellChecker getSpellChecker( ) { 10 return spellChecker; 11 } 12 public void spellCheck() { 13 spellChecker.checkSpelling(); 14 } 15 }
消除set方法
1 package com.tutorialspoint; 2 import org.springframework.beans.factory.annotation.Autowired; 3 public class TextEditor { 4 @Autowired 5 private SpellChecker spellChecker; 6 public TextEditor() { 7 System.out.println("Inside TextEditor constructor." ); 8 } 9 public SpellChecker getSpellChecker( ){ 10 return spellChecker; 11 } 12 public void spellCheck(){ 13 spellChecker.checkSpelling(); 14 } 15 }
消除<constructor-arg>元素
1 package com.tutorialspoint; 2 import org.springframework.beans.factory.annotation.Autowired; 3 public class TextEditor { 4 private SpellChecker spellChecker; 5 @Autowired 6 public TextEditor(SpellChecker spellChecker){ 7 System.out.println("Inside TextEditor constructor." ); 8 this.spellChecker = spellChecker; 9 } 10 public void spellCheck(){ 11 spellChecker.checkSpelling(); 12 } 13 }
修饰set方法
和@Required有相同效果,被@Autowired修饰的set方法中的对象属性,必须在<bean>元素中赋值。
默认是@Autowired(required=true)
1 package com.tutorialspoint; 2 import org.springframework.beans.factory.annotation.Autowired; 3 public class Student { 4 private Integer age; 5 private String name; 6 @Autowired(required=false) 7 public void setAge(Integer age) { 8 this.age = age; 9 } 10 public Integer getAge() { 11 return age; 12 } 13 @Autowired 14 public void setName(String name) { 15 this.name = name; 16 } 17 public String getName() { 18 return name; 19 } 20 }
通常@Qualifier与@Autowired一起使用。
主要用于beans.xml中有多个相同类型的bean,而只需要其中一个bean来装配。
1 package com.tutorialspoint; 2 import org.springframework.beans.factory.annotation.Autowired; 3 import org.springframework.beans.factory.annotation.Qualifier; 4 public class Profile { 5 @Autowired 6 @Qualifier("student1") 7 private Student student; 8 public Profile(){ 9 System.out.println("Inside Profile constructor." ); 10 } 11 public void printAge() { 12 System.out.println("Age : " + student.getAge() ); 13 } 14 public void printName() { 15 System.out.println("Name : " + student.getName() ); 16 } 17 }
<?xml version="1.0" encoding="UTF-8"?> <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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:annotation-config/> <!-- Definition for profile bean --> <bean id="profile" class="com.tutorialspoint.Profile"> </bean> <!-- Definition for student1 bean --> <bean id="student1" class="com.tutorialspoint.Student"> <property name="name" value="Zara" /> <property name="age" value="11"/> </bean> <!-- Definition for student2 bean --> <bean id="student2" class="com.tutorialspoint.Student"> <property name="name" value="Nuha" /> <property name="age" value="2"/> </bean> </beans>
1 package com.tutorialspoint; 2 3 import javax.annotation.PostConstruct; 4 import javax.annotation.PreDestroy; 5 6 public class TextEditor { 7 8 SpellChecker s; 9 10 public TextEditor(SpellChecker spellChecker) { 11 System.out.println("TextEditor的1参构造函数"); 12 this.s = spellChecker; 13 } 14 15 public void spellCheck() { 16 s.checkSpelling(); 17 } 18 19 @PostConstruct 20 public void init() { 21 System.out.println("textEditor bean init()"); 22 } 23 24 @PreDestroy 25 public void destroy() { 26 System.out.println("textEditor bean destroy()"); 27 } 28 29 }
1 // beans.xml 2 // 没有指定<bean>的init-method和destroy-method属性 3 <context:annotation-config/> 4 <bean id="textEditor" class="com.tutorialspoint.TextEditor" autowire="byName"> 5 <constructor-arg ref="spellChecker"></constructor-arg> 6 </bean> 7 <bean id="spellChecker" class="com.tutorialspoint.SpellChecker"></bean>
可修饰属性和set方法
修饰属性:
// TextEditor.java package com.tutorialspoint; import javax.annotation.Resource; public class TextEditor { @Resource(name="spellChecker") SpellChecker s; public TextEditor(SpellChecker spellChecker) { System.out.println("TextEditor的1参构造函数"); this.s = spellChecker; } public void spellCheck() { s.checkSpelling(); } } // beans.xml <context:annotation-config></context:annotation-config> <bean id="textEditor" class="com.tutorialspoint.TextEditor"></bean> <bean id="spellChecker" class="com.tutorialspoint.SpellChecker"></bean>
修饰set方法
1 // TextEditor.java 2 package com.tutorialspoint; 3 import javax.annotation.Resource; 4 public class TextEditor { 5 6 SpellChecker s; 7 8 public TextEditor(SpellChecker spellChecker) { 9 System.out.println("TextEditor的1参构造函数"); 10 this.s = spellChecker; 11 } 12 13 public SpellChecker getS() { 14 return s; 15 } 16 17 @Resource(name="spellChecker") 18 public void setS(SpellChecker s) { 19 this.s = s; 20 } 21 22 public void spellCheck() { 23 s.checkSpelling(); 24 } 25 26 } 27 28 // beans.xml 29 <context:annotation-config></context:annotation-config> 30 31 <bean id="textEditor" class="com.tutorialspoint.TextEditor"></bean> 32 <bean id="spellChecker" class="com.tutorialspoint.SpellChecker"></bean>
注意:@Resource不可修饰构造函数
@Configuration注解类表示定义bean的来源
@bean注解的方法将返回一个对象,不管是利用构造方法还是其他方法,一定要返回一个对象。类似于beans.xml中的<bean>元素
不需要beans.xml文件
1 // HelloWorldConfig.java 2 package com.tutorialspoint; 3 4 import org.springframework.context.annotation.Bean; 5 import org.springframework.context.annotation.Configuration; 6 7 @Configuration 8 public class HelloWorldConfig { 9 @Bean 10 public HelloWorld helloWorld() { 11 return new HelloWorld(); 12 } 13 } 14 15 // HelloWorld.java 16 package com.tutorialspoint; 17 18 public class HelloWorld { 19 String message; 20 21 public String getMessage() { 22 System.out.println("Your Message:"+message); 23 return message; 24 } 25 26 public void setMessage(String message) { 27 this.message = message; 28 } 29 30 } 31 32 // MainApp.java 33 public class MainApp { 34 public static void main(String[] args) { 35 ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfig.class); 36 HelloWorld helloWorld = context.getBean(HelloWorld.class); 37 helloWorld.setMessage("Hello World!"); 38 helloWorld.getMessage(); 39 } 40 }
1 // Foo.java 2 package com.tutorialspoint; 3 4 public class Foo { 5 Bar bar; 6 7 public Foo(Bar bar) { 8 System.out.println("Foo 1参构造函数"); 9 this.bar = bar; 10 } 11 } 12 13 // Bar.java 14 package com.tutorialspoint; 15 16 public class Bar { 17 public Bar() { 18 System.out.println("Bar无参构造函数"); 19 } 20 } 21 22 // AppConfig.java 23 package com.tutorialspoint; 24 25 import org.springframework.context.annotation.Bean; 26 import org.springframework.context.annotation.Configuration; 27 28 @Configuration 29 public class AppConfig { 30 @Bean 31 public Foo foo() { 32 return new Foo(new Bar()); 33 } 34 35 @Bean 36 public Bar bar() { 37 return new Bar(); 38 } 39 } 40 41 // MainApp.java 42 package com.tutorialspoint; 43 44 import org.springframework.context.ApplicationContext; 45 import org.springframework.context.annotation.AnnotationConfigApplicationContext; 46 47 public class MainApp { 48 public static void main(String[] args) { 49 ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); 50 Foo foo = ctx.getBean(Foo.class); 51 } 52 }
1 // Foo.java 2 package com.tutorialspoint; 3 4 public class Foo { 5 Bar bar; 6 7 public Foo() { 8 System.out.println("Foo无参构造函数"); 9 } 10 11 public Bar getBar() { 12 return bar; 13 } 14 15 public void setBar(Bar bar) { 16 this.bar = bar; 17 } 18 19 } 20 21 // Bar.java 22 package com.tutorialspoint; 23 24 public class Bar { 25 public Bar() { 26 System.out.println("Bar无参构造函数"); 27 } 28 } 29 30 // AppConfig.java 31 package com.tutorialspoint; 32 33 import org.springframework.context.annotation.Bean; 34 import org.springframework.context.annotation.Configuration; 35 36 @Configuration 37 public class AppConfig { 38 @Bean 39 public Foo method() { 40 Foo foo = new Foo(); 41 foo.setBar(bar());// method注入 42 return foo; 43 } 44 45 @Bean 46 public Bar bar() { 47 return new Bar(); 48 } 49 } 50 51 // MainApp.java 52 package com.tutorialspoint; 53 54 import org.springframework.context.ApplicationContext; 55 import org.springframework.context.annotation.AnnotationConfigApplicationContext; 56 57 public class MainApp { 58 public static void main(String[] args) { 59 ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); 60 Foo foo = ctx.getBean(Foo.class); 61 } 62 }
从另一个配置类中加载@Bean定义
// A.javapublic class A { public A() { System.out.println("A无参constructor"); } public void methodOfA() { System.out.println("A中的方法"); } } // B.javapublic class B { A a; public B(A a) { System.out.println("B 1参构造函数"); this.a = a; } public void method() { a.methodOfA(); } } // ConfigA.java @Configuration public class ConfigA { @Bean public A a() { return new A(); } } // ConfigB.java @Configuration @Import(ConfigA.class) public class ConfigB { @Bean B b() { return new B(new A()); } } // MainApp.javapublic class MainApp { public static void main(String[] args) { // 当实例化上下文时,不需要同时指定 ConfigA.class 和 ConfigB.class,只有 ConfigB 类需要提供 ApplicationContext context = new AnnotationConfigApplicationContext(ConfigB.class); A a = context.getBean(A.class); B b = context.getBean(B.class);
a.methodOfA(); b.method(); } }
1 // A.java 2 public class A { 3 public A() { 4 System.out.println("A无参constructor"); 5 } 6 7 public void init() { 8 System.out.println("A init()"); 9 } 10 11 public void cleanup() { 12 System.out.println("A cleanup()"); 13 } 14 15 public void methodOfA() { 16 System.out.println("A中的方法"); 17 } 18 } 19 20 // ConfigA.java 21 @Configuration 22 public class ConfigA { 23 @Bean(initMethod="init", destroyMethod="cleanup") 24 public A a() { 25 return new A(); 26 } 27 } 28 29 // MainApp.java 30 public class MainApp { 31 public static void main(String[] args) { 32 AbstractApplicationContext context = new AnnotationConfigApplicationContext(ConfigA.class); 33 A a = context.getBean(A.class); 34 a.methodOfA(); 35 context.registerShutdownHook(); 36 } 37 }
标签:两种 tutorials space [] clean xmla tar bean gis
原文地址:https://www.cnblogs.com/yfs123456/p/10666804.html