什么是SpringIOC
spring ioc指的是控制反转,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。交由Spring容器统一进行管理,从而实现松耦合。
控制反转是一种通过描述(在Java中可以是xml或注解)并通过第三方去产生或者获取对象的方式
SpringIOC容器的设计主要是基于BeanFactory和AppilicationContext两个接口
BeanFactory是Spring定义的最底层的接口,AppilicationContext是BeanFactory的子接口之一
BeanFactory中定义了多个抽象方法
getBean 用于获取配置给SpringIOC容器的bean
isSingle 单例
isPrototype 多例
getAliases 获取别名
ApplicationContext的间接实现类ClassPathXmlApplicationContext
spring-config.xml:
<beans …>
<bean id="userDaoImpl" class="dao.impl.UserDaoImpl"></bean>
<bean id="userBizImpl" class="biz.impl.UserBizImpl" scope="singleton">
<property name="bName" value="bName1"></property>
<property name="bNum" value="1"></property>
<property name="userDao" ref="userDaoImpl"></property>(注入自定义类)
</bean>
</beans>
这里定义了两个bean,这样SpringIOC容器在初始化的时候就能找到他们,然后使用ClassPathXmlApplicationContext就可以将其初始化。
ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml "});
UserBiz userBiz = (UserBiz) ac.getBean("userBizImpl");
Spring bean要先初始化,才会进行依赖注入
初始化的3个步骤:
(1) resource定位,通过xml或者注解的方式定位
(2) beandefinition的载入,spring通过配置获取pojo(用于生成实例)
(3) beandefinition的注册,把载入的pojo往springIOC容器中注册
这样就可以得到springIOC容器的bean了。
setter注入
spring-config.xml文件:
<beans …>
<bean id="userDaoImpl" class="dao.impl.UserDaoImpl"></bean>
<bean id="userBizImpl" class="biz.impl.UserBizImpl" scope="singleton">
<property name="bName" value="bName1"></property>
<property name="bNum" value="1"></property>
<property name="userDao" ref="userDaoImpl"></property>(注入自定义类)
</bean>
</beans>
注意:配bean时候,若没有写id,则spring将会采用“全限定名#{number}”的格式生成编号,如:
biz.impl.UserBizImpl #1、biz.impl.UserBizImpl#2
userBizImpl.java文件:
private String bName;
private int bNum;
private UserDao userDao;
/*** getter setter ***/
Test.java文件:
ApplicationContext ac = new ClassPathXmlApplicationContext(new String[]{"spring-config.xml "});
UserBiz userBiz = (UserBiz) ac.getBean("userBizImpl");
注意:
scope属性表示bean的作用域 不写默认是单例模式singleton,每次实例化bean都是同一个bean
prototype多例 每次实例化bean都是新的,
request 每次请求时实例化bean是新的
session 浏览器打开关闭之间实例化bean是新的
global session 相当于 application 服务器打开关闭之间实例化bean是新的
构造注入
application.xml文件:
<bean id="userDaoImpl" class="dao.impl.UserDaoImpl"></bean>
<bean id="userBizImpl3" class="biz.impl.UserBizImpl" scope="singleton">
<constructor-arg index="0" value="bName3"></constructor-arg>
<constructor-arg index="1" value="3"></constructor-arg>
<constructor-arg index="2" ref="userDaoImpl"></constructor-arg>
</bean>
userBizImpl.java文件,需要有对应的构造器:
//需要有对应的构造器
public UserBizImpl(String bName, int bNum,UserDao userDao) {
super();
this.bName = bName;
this.bNum = bNum;
this.userDao = userDao;
}
工厂方法注入(静态工厂、非静态工厂)
通过注解装配bean
@Component
Role.java文件:
@Component(value="role")
public class Role {
@Value("123")//这里 id是long型 spring注入时候会为其转型
private Long id;
@Value("role_name_1")
private String roleName;
@Value("note1")
private String note;
}
注意:@Component(value=“role”)//相当于xml方式,定义bean中的id不写@Component 默认为类名并且首字母小写
PojoConfig.java文件:
@Configuration
@ComponentScan
public class PojoConfig {
}
Test.java文件:
ApplicationContext ac = new AnnotationConfigApplicationContext(PojoConfig.class);
Role role = (Role) ac.getBean("role");//也可以这么获取Role role = ac.getBean(Role.class);
System.out.println(role.getId());
打印结果 123
注意:
@ComponentScan只会扫描所在包的Java类,若需要指定哪些类则需
@ComponentScan(basePackageClasses = {Role.class,User.class} )
或者
@ComponentScan(basePackages = {“entity.Role”,“biz.impl”})
@Autowired
@Autowired
private Role role;
也可以在setter方法上注解:
@Autowired
public void setRole(Role role) {
this.role = role;
}
注意:
@Autowired默认情况下,spring会认为一定要找到对应的bean注入这个字段,否则报错,但有时候可有可无,则需
@Autowired(required = false)
@Primary和@Qualifier
当下面这个UserDao有多个实现类的时候,spring就不知道该注入哪个实现类了就会报错
@Autowired
private UserDao userDao;
那么需要这么解决,表示优先注入这个实现类
@Primary
public class UserDaoImpl2 implements UserDao{
}
或者
@Autowired
@Qualifier("userDaoImpl2")
private UserDao userDao;