传统的实现,需要自己new对象,然后给对象属性赋值,一旦有改动,特别麻烦。
class UserService{
UserDao userDao = new UserDao();
}
后来,使用DaoFactory,通过字符串创建对应的对象。
private UserDao userDao = DaoFactory.getInstance().createDao("zhongfucheng.dao.impl.UserDaoImpl", UserDao.class);
public class DaoFactory {
private static final DaoFactory factory = new DaoFactory();
private DaoFactory(){}
public static DaoFactory getInstance(){
return factory;
}
public <T> T createDao(String className,Class<T> clazz){
try{
T t = (T) Class.forName(className).newInstance();
return t;
}catch (Exception e) {
throw new RuntimeException(e);
}
}
}
再后来,我们在DaoFactory中读取配置文件,根据配置文件来创建对象
UserDao dao = DaoFactory.getInstance().createUserDao();
public class DaoFactory {
private UserDao userdao = null;
private DaoFactory(){
try{
InputStream in = DaoFactory.class.getClassLoader().getResourceAsStream("dao.properties");
Properties prop = new Properties();
prop.load(in);
String daoClassName = prop.getProperty("userdao");
userdao = (UserDao)Class.forName(daoClassName).newInstance();
}catch (Exception e) {
throw new RuntimeException(e);
}
}
private static final DaoFactory instance = new DaoFactory();
public static DaoFactory getInstance(){
return instance;
}
public UserDao createUserDao(){
return userdao;
}
}
对象之间的依赖关系,其实就是给对象上的属性赋值!因为对象上有其他对象的变量,因此存在了依赖。
Spring提供了好几种的方式来给属性赋值
在serice中加入一个构造函数,参数就是userDao
public class UserService {
private UserDao userDao;
public UserService(UserDao userDao) {
this.userDao = userDao;
}
}
applicationContext.xml配置文件
<!--创建userDao对象-->
<bean id="userDao" class="UserDao"/>
<!--创建userService对象-->
<bean id="userService" class="UserService">
<!--要想在userService层中能够引用到userDao,就必须先创建userDao对象-->
<constructor-arg index="0" name="userDao" type="UserDao" ref="userDao"></constructor-arg>
</bean>
在service层通过set方法来把userDao注入到UserService中
public class UserService {
private UserDao userDao;
public void setUserDao(String userId,String userName) {
UserDao userDao = new UserDao();
userDao.setId(userId);
userDao.setName(userName);
this.userDao = userDao;
}
}
applicationContext.xml配置文件:通过property节点来给属性赋值,引用类型使用ref属性,基本类型使用value属性。
<!--创建userDao对象-->
<bean id="userDao" class="UserDao"/>
<!--创建userService对象-->
<bean id="userService" class="UserService">
<property name="userDao" ref="userDao"/>
</bean>
内部Bean
先创建userService,发现userService需要userDao的属性,再创建userDao。缺点是如果Bean要多次被使用的话,就要多次配置。
applicationContext.xml配置文件:property节点内置bean节点
<!--
1.创建userService,看到有userDao这个属性
2.而userDao这个属性又是一个对象
3.在property属性下又内置了一个bean
4.创建userDao
-->
<bean id="userService" class="UserService">
<property name="userDao">
<bean id="userDao" class="UserDao"/>
</property>
</bean>
p 名称空间注入属性值
applicationContext.xml配置文件:使用p名称空间
<bean id="userDao" class="UserDao"/>
<!--不用写property节点了,直接使用p名称空间-->
<bean id="userService" class="UserService" p:userDao-ref="userDao"/>
自动装载默认是不打开的,修改applicationContext.xml配置文件使其生效。
byName:通过参数名自动装配,装配和该bean的属性具有相同名字的bean。
<bean id="userDao" class="UserDao"/>
<!--
1.通过名字来自动装配
2.发现userService中有个叫userDao的属性
3.看看IOC容器中没有叫userDao的对象
4.如果有,就装配进去
-->
<bean id="userService" class="UserService" autowire="byName"/>
byType:通过参数类型自动装配,装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
<bean id="userDao" class="UserDao"/>
<!--
1.通过名字来自动装配
2.发现userService中有个叫userDao的属性
3.看看IOC容器UserDao类型的对象
4.如果有,就装配进去
-->
<bean id="userService" class="UserService" autowire="byType"/>
@Resource默认通过反射按名称装配,找不到才按类型装配。 使用name属性指定byName策略,使用type属性指定byType策略。
@Autowired注解来实现自动装配。 默认按类型装配。结合@Qualifier(“name”)按照名称装配。required属性为false时允许null值。
@Component
public class UserService {
@Autowired
private UserDao userDao ;
// @Autowired
// public void setUserDao(UserDao userDao) {
// this.userDao = userDao;
// }
}
**Spring使用依赖注入来实现对象之间的依赖关系 ** DI dependency injection。
Spring将对象的创建交给外部容器完成称为控制反转 IOC Inversion of Control。
这个外部容器就是IOC容器。
使用IOC的优点:
缺点:对象生成因为是使用反射编程,在效率上有损耗
IOC容器是个Bean工厂,管理我们所有的对象以及依赖关系。
Spring IOC容器实现对象的创建和依赖的步骤:
IOC容器装配Bean方法
IOC容器是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从真正的应用代码中分离。可简单分成两种:
区别:
参考:
Spring入门这一篇就够了:https://mp.weixin.qq.com/s/gGzgLaiTzpGemPw_h_r-Hw
Spring【依赖注入】就是这么简单:https://mp.weixin.qq.com/s/7eAnJw10VHdt6N5ZteTMhg
Spring IOC知识点一网打尽:https://mp.weixin.qq.com/s/TYftOpe6J1Y4EDNDxKKqXg
Spring思维导图(ioc篇):https://segmentfault.com/a/1190000017348726
Spring的IOC,属性注入,bean的理解:https://blog.csdn.net/weixin_41737632/article/details/109615913
SpringIOC和AOP原理 设计模式:https://www.jianshu.com/p/40d0a6ad21d2