基于XML的Spring应用
SpringBean配置详解
XML配置方式 | 功能描述 |
---|---|
id | Bean的id和全限定名配置,通过反射机制实现,如果不配id,就是bean的当前权限名class;如果没有配置id,而配置了name那么别名的第一个就是它的id |
name | 为Bean设置别名,在没有设置的情况下,name就是id |
scope | 包含singleton和prototype,主要区别在于创建实际的不同以及是否存放到单例池中,prototype在getbean时才会创建,并且不会存储到单例池中 |
lazy-init | 延迟加载,在使用ApplicationContext的情况下会在加载文件的时候直接创建,通过lazy-init我们可以让它进行延迟加载,首次getbean时候创建。只对ApplicationContext有效 |
init-method | 在完成Bean对象实例化之后执行。先执行构造方法,然后才是init方法 |
destroy-method | 只有在显式关闭的时候才会被调用。 |
autowire | 设置自动注入,可以按照类型也可以按照名字 |
factory-bean和factory-method | 指定使用哪个工厂Bean的哪个方法完成Bean的创建 |
别名的使用
<!-- 多个别名通过逗号隔开 如果没有配置id,而配置了name那么别名的第一个就是它的id -->
<bean id="userService" name="aaa,bbb" class="com.itheima.service.impl.UserServiceimpl">
<!-- 将userDao传入到setUserDao方法中 注意这边使用的是ref标签 -->
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.itheima.service.dao.impl.UserDaoImpl"/>
Scope的测试使用
通过打断点的方式找到BeanFacory中的SingletonObject中的实例对象进行验证
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserServiceimpl userService = (UserServiceimpl) applicationContext.getBean("userService");
UserServiceimpl userService2 = (UserServiceimpl) applicationContext.getBean("userService");
UserServiceimpl userService3 = (UserServiceimpl) applicationContext.getBean("userService");
// userService.show();
System.out.println(userService);
System.out.println(userService2);
System.out.println(userService3);
}
<!-- 多个别名通过逗号隔开 如果没有配置id,而配置了name那么别名的第一个就是它的id -->
<bean id="userService" name="aaa,bbb" class="com.itheima.service.impl.UserServiceimpl" scope="singleton">
<!-- 将userDao传入到setUserDao方法中 注意这边使用的是ref标签 -->
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.itheima.service.dao.impl.UserDaoImpl"/>
Lazy-init的测试使用代码和上面基本一致
在测试过程中注意使用打断点方式进行验证
Destroy-Method和init-Method
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserServiceimpl userService = (UserServiceimpl) applicationContext.getBean("userService");
// userService.show();
System.out.println(userService);
applicationContext.close();
}
<!-- 多个别名通过逗号隔开 如果没有配置id,而配置了name那么别名的第一个就是它的id -->
<bean id="userService" name="aaa,bbb" class="com.itheima.service.impl.UserServiceimpl" init-method="init" destroy-method="destroy">
<!-- 将userDao传入到setUserDao方法中 注意这边使用的是ref标签 -->
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.itheima.service.dao.impl.UserDaoImpl"/>
InitializingBean方法
在属性设置之后会执行这个方法,也就是哪些setxxx方法执行之后,在init-method之前
public class UserServiceimpl implements UserService, InitializingBean {
private UserDao userDao;
public UserServiceimpl(){
System.out.println("UserServiceimple Create");
}
public void init(){
System.out.println("init_method...");
}
// 该方法由BeanFactory进行调用,从容器中获取UserDao设置到此位置
public void setUserDao(UserDao userDao){
// System.out.println("UserDao input UserService: " + userDao);
this.userDao = userDao;
}
public void destroy(){
System.out.println("destroy_method...");
}
// 在属性设置之后执行,也就是在在所有set执行完之后
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet executing");
}
}
实例化有参构造方法
<!-- 多个别名通过逗号隔开 如果没有配置id,而配置了name那么别名的第一个就是它的id -->
<bean id="userService" name="aaa,bbb" class="com.itheima.service.impl.UserServiceimpl" init-method="init" destroy-method="destroy">
<constructor-arg name="args" value="123123123"/>
<!-- 将userDao传入到setUserDao方法中 注意这边使用的是ref标签 -->
<property name="userDao" ref="userDao"/>
</bean>
静态工厂方法
public class MyBeanFactory1 {
public static UserDao userDao(){
return new UserDaoImpl();
}
}
<!-- 静态工厂方法 -->
<!-- 通过静态工厂方法,能够将com.itheima.service.factory.MyBeanFactory1中的userDao方法的返回值作为创建的bean对象 -->
<bean id="userDao1" class="com.itheima.service.factory.MyBeanFactory1" factory-method="userDao"/>
实例工厂对象方法
静态工厂和动态的区别在于静态工厂直接指定class的方法创建一个Bean对象,实例工厂则是通过已有的某个Bean的其中一个方法创建一个Bean。
<!-- 实例工厂方法 -->
<bean id="userDao2" class="com.itheima.service.factory.MyBeanFactory2"/>
<bean id="myBeanFactory2" factory-bean="beanFactory2" factory-method="userDao"/>
有参形式
<bean id="userDao1" class="com.itheima.service.factory.MyBeanFactory1" factory-method="userDao">
<constructor-arg name="name" value="name"/>
<constructor-arg name="age" value="11"/>
</bean>
实现FactoryBean规范延迟Bean实例化
public class MyBeanFactory3 implements FactoryBean<UserDao> {
// 在程序getBean的时候获取的并不是MyBeanFactory3,而是getObject方法的返回对象,在main中打断点测试可以发现这个UserDao是被加载到factoryBeanObjectCache中,并且是在getbean时候被放入的,存在延迟加载
@Override
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
@Override
public Class<?> getObjectType() {
return UserDao.class;
}
}
参数注入
不管是property还是constructor-arg,如果是普通的参数值都是用value,如果是bean的引用就是用ref
<bean id="userService" name="aaa,bbb" class="com.itheima.service.impl.UserServiceimpl" init-method="init" destroy-method="destroy">
<constructor-arg name="args" value="123123123"/>
<!-- 将userDao传入到setUserDao方法中 注意这边使用的是ref标签 -->
<property name="userDao" ref="userDao"/>
</bean>
如果是集合,List Map等
<bean id="userService" name="aaa,bbb" class="com.itheima.service.impl.UserServiceimpl" init-method="init" destroy-method="destroy">
<constructor-arg name="args" value="123123123"/>
<!-- 将userDao传入到setUserDao方法中 注意这边使用的是ref标签 -->
<property name="userDao" ref="userDao"/>
<!-- 传入List集合参数 -->
<property name="stringList">
<list>
<value>aaa</value>
<value>bbb</value>
</list>
</property>
<property name="userDaoList">
<list>
<bean class="com.itheima.service.dao.impl.UserDaoImpl"></bean>
<ref bean="userDao"></ref>
</list>
</property>
</bean>
<!-- set数据类型 -->
<property name="strSet">
<set>
<value>xxx</value>
<value>yyy</value>
</set>
</property>
<property name="userDaoSet">
<set>
<ref bean="userDao"></ref>
</set>
</property>
<!-- Map以及Properties -->
<property name="userDaoMap">
<map>
<entry key="d1" value-ref="userDao"></entry>
</map>
</property>
<property name="properties">
<props>
<prop key="p1">ppp1</prop>
</props>
</property>
Bean的自动装配
自动装配是指对创建Bean对象的时候,如果其类的内部存在Set方法设置一些参数,那么autowire
将会根据名字或者类型进行自动参数输入。
Byname
:根据beanName进行装配ByType
:根据类型进行装配
<!-- autowire userService中的一些set方法将根据其name进行自动的装填配置 -->
<bean id="userService" class="com.itheima.service.impl.UserServiceimpl" autowire="byType"/>
<bean id="userDao" class="com.itheima.service.dao.impl.UserDaoImpl"/>
命名空间的种类
第一个xmln表示默认命名空间,第二行的那个在时候的时候是要加上xsi:…;如果需要加上自己需要的标签就可以相应添加,例如这里的context
<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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
标签的使用
beans标签可通过prifile来区分测试环境与运行环境 ,如果没有被包含在任何环境下的默认标签,则表示公共使用,另外beans在使用的时候需要放在默认标签的后面,否则会报错,存在顺序问题。
<beans profile="dev">
<bean id="xxxx" class="com.itheima.service.impl.UserServiceimpl"></bean>
</beans>
<beans profile="test">
<bean id="xxxx" class="com.itheima.service.impl.UserServiceimpl"></bean>
</beans>
public static void main(String[] args) {
// 指定需要的springXML环境
System.setProperty("spring.profiles.active","dev");
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("xxxx");
userService.show();
applicationContext.close();
}
导入配置其他的xml文件
<import resource="classpath:beans.xml"></import>
标签为bean取别名
<!-- name参数是bean的name,alias是新设置的别名 其实和bean中的name作用一样-->
<alias name="userDao" alias="dao"/>
引入第三方命名空间
- 首先需要找到对应的jar包
- 然后通过网络资料在命名空间中夹着对应的配置
- 最后可以直接使用
三种不同的getbean方式
// 通过beanname进行获取
UserService userService = (UserService) applicationContext.getBean("userService");
// 通过Bean的参数类型以及name进行获取
UserService userService1 = applicationContext.getBean("userService", UserService.class);
// 通过bean类型进行获取,这种方法要求类型唯一 这里也可以写UserServiceimple.class
UserService userService2 = applicationContext.getBean(UserService.class);