自动装配
1、简介
IoC容器可以根据bean的名称、类型或构造方法自动进行注入,称为自动装配。
只针对其他bean的引用
2、配置方式(根据实际例子来说明)
<?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">
<!--手工注入otherBean 需要set方法-->
<!--SpringBean类中需要一个OtherBean实例,这里通过ref属性手动注入一个otherBean-->
<!--<bean id="springBean" class="ioc17.SpringBean">
<property name="otherBean" ref="otherBean"/>
</bean>-->
<!--自动装配-->
<!--
autowire:取值
default 不自动进行装配(默认值)
byName 根据属性名进行自动装配,查找与属性名(otherBean)同名的bean
bytype 根据属性的类型自动装配,查找与属性同类型(OtherBean)的bean (工作中常用)
如果刚好找到一个同类的型则注入
如果找到多个同类型的bean,则抛出异常
constructor 根据构造方法自动装配
同时根据byName和byType自动装配,先按byName,再按byType
注意:此时不是通过set方法进行装配的,所以可不写对应的set方法
-->
<!--<bean id="springBean" class="ioc17.SpringBean" autowire="byName"/>-->
<!--<bean id="springBean" class="ioc17.SpringBean" autowire="byType"/>-->
<!--
该配置告诉springBean要用构造方法进行注入,在注入springBean时需要一个otherBean,
IoC根据是否有一个构造方法参数是带otherBean的,如果确实有一个形参名叫otherBean,则就注入进去,
-->
<bean id="springBean" class="ioc17.SpringBean" autowire="constructor"/>
<!--与ob属于同类型-->
<bean id="otherBean" class="ioc17.OtherBean">
<property name="username" value="lucy"/>
</bean>
<!--与otherBean属于同类型-->
<bean id="ob" class="ioc17.OtherBean">
<property name="username" value="alice"/>
</bean>
</beans>
package ioc17;
public class OtherBean {
private String username;
@Override
public String toString() {
return "OtherBean{" +
"username='" + username + '\'' +
'}';
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
package ioc17;
public class SpringBean {
private OtherBean otherBean;
public SpringBean(OtherBean otherBean) {
System.out.println("SpringBean.SpringBean.OtherBean");
this.otherBean = otherBean;
}
public OtherBean getOtherBean() {
System.out.println("SpringBean.SpringBean");
return otherBean;
}
/*
autowire不是constructor时要使用set方法,
如果autowire="constructor"那么不要使用set方法
*/
public void setOtherBean(OtherBean otherBean) {
this.otherBean = otherBean;
}
}
package ioc17;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String [] args){
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc17/spring.xml");
SpringBean springBean = (SpringBean) ac.getBean("springBean");
System.out.println(springBean.getOtherBean());
}
}
在Bean中获取IoC容器
1、定义一个IoC容器工具类
步骤:
1、定义一个类,实现ApplicationContextAware接口
2、将该工具bean添加到IoC容器中
3、调用工具类,获取IoC容器中的bean
2、基本用法
<?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">
<!--在bean中获取容器-->
<bean id="springBean" class="ioc18.SpringBean">
<property name="username" value="tom"/>
</bean>
<!--
将工具bean添加到IoC容器中
因为ApplicationContextHolder实现了ApplicationContextAware接口,
所以spring就自动把IoC容器通过setApplicationContext方法自动注入给应用类
-->
<bean class="ioc18.ApplicationContextHolder"/>
</beans>
package ioc18;
public class SpringBean {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public String toString() {
return "SpringBean{" +
"username='" + username + '\'' +
'}';
}
}
package ioc18;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
/*
* 作用:实例化该工具类的时候,会自动把当前应用的IoC容器注入到该工具类
* 该工具类本身要在IoC容器中注册,否则IoC不认识该类,也不会把ApplicationContext注入
* description:IoC容器的工具类,获取并操作IoC容器
*/
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext ac;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ac = applicationContext;
}
//获取IoC容器
//一般不直接提供ApplicationContext的方法,不安全,用户ac=null就完蛋了
/*public static ApplicationContext getApplicationContext(){
return ac;
}*/
//该方法安全
//按bean的名字获取
public static Object getBean(String beanName){
return ac.getBean(beanName);
}
//传入对象类型 class对象
//但是多线程并发会出问题
public static <T> T getBean(Class<T> clazz){
return ac.getBean(clazz);
}
}
package ioc18;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String [] args){
//指定配置文件初始化spring上下文,并创建一个IoC容器,然后返回该IoC容器
//new多个springIoC,再获取bean,得到的是不同的bean,因为是不同spring IoC的创建的bean
ApplicationContext ac = new ClassPathXmlApplicationContext("ioc18/spring.xml");
/*SpringBean springBean = (SpringBean) ac.getBean("springBean");
System.out.println(springBean);*/
//拿到IoC容器
/*ac = ApplicationContextHolder.getApplicationContext();
SpringBean springBean = (SpringBean) ac.getBean("springBean");
System.out.println(springBean.getUsername());*/
//安全的方式获取IoC管理的bean中的属性值
SpringBean springBean2 = (SpringBean) ApplicationContextHolder.getBean("springBean");
System.out.println(springBean2.getUsername());
//安全的方式获取
SpringBean springBean3 = ApplicationContextHolder.getBean(SpringBean.class);
System.out.println(springBean3.getUsername());
}
}