1.1、IOC
IOC分别控制反转和依赖注入。
所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
控制反转(IOC:Inversion of Control):将对象的实例化交由spring来负责创建,说白了就是在xml中配置对象的bean实例。
依赖注入(DI: Dependency injection):在创建对象实例时,为这个对象注入属性值或其它对象实例。
1.1.1、依赖注入方式:(配置版)
-
设值注入:通过setXxx()方法注入(个人推荐:可以灵活组合)
1、需要使用setXxx()方法,在application.xml文件中使用
UserServiceImpl.java中
public class UserServiceImpl implements UserService { // private UserDao userDao=new UserDaoImpl();//死代码 private UserDao userDao; private String name; private String sex; public void setUserDao(UserDao userDao) { this.userDao = userDao; } public void setName(String name) { this.name = name; } public UserServiceImpl() { } public UserServiceImpl(UserDao userDao, String name,String sex) { this.userDao = userDao; this.name = name; this.sex=sex; } @Override public int addUser(User entity) { System.out.println("name:"+name+",sex:"+sex); return userDao.addUser(entity); } }
application.xml中:
<bean id="userService" class="com.ioc.conf.service.impl.UserServiceImpl">
<!-- 设值注入 -->
<property name="userDao" ref="userDao" />
<property name="name" value="张三" />
</bean>
-
构造注入:通过构造方法注入
UserServiceImpl.java中需要提供构造函数
application.xml中
<bean id="userService" class="com.ioc.conf.service.impl.UserServiceImpl"> <!-- 构造注入 --> <!-- index:配置对应构造参数的位置,从0开始 <constructor-arg index="0" ref="userDao" /> <constructor-arg index="2" value="男" /> <constructor-arg index="1" value="张三" /> --> </bean>
-
p命名空间注入:
第一步:需要p命名空间的声明
xmlns:p="http://www.springframework.org/schema/p"
第二步:使用
<!-- p命名空间注入 --> <!-- p:属性名:配置的常量值 p:属性名-ref:配置引用类型的名称 --> <bean id="country1" class="com.ioc.conf.entity.Country" p:name="中国" /> <bean id="user1" class="com.ioc.conf.entity.User" p:id="1" p:loginName="admin" p:password="123" p:country-ref="country1" />
1.1.2、singleton和prototype
singleton:单例(默认值)
prototype:多例
<bean id="userService" class="com.ioc.conf.service.impl.UserServiceImpl"
scope="prototype">
</bean>
1.1.3、自动装配
spring提供了4种自动装配类型
取值 | 说明 |
---|---|
no | 默认值,spring默认不进行自动装配,必须显示指定依赖对象 |
byType | 根据属性类型自动装配,如果找到多个报错,只有找到唯一的那个,才会自动注入。如果找不到,什么也不做。 |
byName | 根据属性名称自动装配,找到bean的id值与属性名相同会自动注入。如果找不到,什么也不做。 |
constructor | 和byType类似,不过它针对的构造方法。如果找到1个 bean和构造方法的参数类型相匹配,则通过构造注入,否则什么也不做。 |
<!-- 第一种:在每个bean中通过autowire属性进行配置 -->
<bean id="userService2" class="com.ioc.conf.service.impl.UserServiceImpl"
scope="prototype" autowire="constructor">
<!-- <property name="userDao" ref="userDao" /> -->
<!-- <property name="name" value="张三" /> -->
</bean>
<!-- 第二种:直接在<beans>标签上配置default-autowire="default“ -->
<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"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"
default-autowire="default">
</beans>
注意:不推荐使用,自动装配使得配置文件可以非常简洁,但同时也造成类型之间的依赖关系不明确,容易引发一些潜在的问题,在实际项目中需要谨慎使用。
1.1.4、基于注解的配置
- @Component:代表组件,表示1个bean实例
- @Controller:用于标注控制层
- @Service:用于标注业务层
- @Repository:用于标注模型层
- @Autowired:自动注入,byType(属于spring的注解)
- @Resource:自动注入,byName(属于j2ee的注解)
- @Qualifier:根据属性名注入:byName
- @Scope:配置singleton和prototype。