如何理解Spring的IoC
(1) IOC就是控制反转。就是对象的创建权反转交给Spring,由容器控制程序之间的依赖关系,作用是实现了程序的解耦合,而非传统实现中,由程序代码直接操控。(依赖)控制权由应用代码本身转到了外部容器,由容器根据配置文件去创建实例并管理各个实例之间的依赖关系,控制权的转移,是所谓反转,并且由容器动态的将某种依赖关系注入到组件之中。BeanFactory是SpringIoC容器的具体实现与核心接口,提供了一个先进的配置机制,使得任何类型的对象的配置成为可能,用来包装和管理各种bean。
(2) 最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,这里用的就是java的反射机制,通过反射在运行时动态的去创建、调用对象。spring就是根据配置文件在运行时动态的去创建对象,并调用对象的方法的。
(3) Spring的IOC有三种注入方式:
第一是根据属性注入,也叫set方法注入;
第二种是根据构造方法进行注入;
第三种是根据p名称空间进行注入。
详细的说:
(4) IoC,控制反转:将对象交给容器管理,你只需要在spring配置文件总配置相应的bean,以及设置相关的属性,让spring容器生成类的实例对象以及管理对象。在spring容器启动的时候,spring会把你在配置文件中配置的bean都初始化以及装配好,然后在你需要调用的时候,就把它已经初始化好的那些bean分配给你需要调用这些bean的类。就是将对象的控制权反转给spring容器管理。
(5) DI机制(DependencyInjection,依赖注入):可以说是IoC的其中一个内容,在容器实例化对象的时候主动的将被调用者(或者说它的依赖对象)注入给调用对象。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。
IoC让相互协作的组件保持松散的耦合,而AOP编程允许你把遍布于应用各层的功能分离出来形成可重用的功能组件。
IOC底层原理
创建User实体类
创建了UserDao接口
创建了UserDaoImpl实现类
@Override
public User findUserById(int id) {
User user = new User();
user.setId(id);
user.setUsername("xxx");
return user;
}
8.4 创建了UserService接口
创建了UserServiceImpl实现类
public class UserServiceImpl implements UserService {
//应用到Dao:
// 传统方式: service代码直接通过new 关键字创建了dao层对象: 耦合度高。
// private UserDao dao = new UserDaoImpl();
//通过工厂获得一个对象:UserServiceImpl 和 UserDaoImpl 进行了解耦合。
private UserDao dao =(UserDao) MyBeanFacory.getInstance();
@Override
public User findUserByIdService(int id) {
return dao.findUserById(id);
}userDao=com.offcn.dao.impl.UserDaoImpl
}
配置文件的创建
创建了userDao.properties属性文件:
userDao=com.offcn.dao.impl.UserDaoImpl
工厂类的创建
package com.offcn.pojo;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* 创建了工厂类:
*/
public class MyBeanFacory {
//静态代码块: 随着类的加载而加载: key value:
private static Properties prop = new Properties();
private static Map<String,Object> map = new HashMap<>();
static {
//将userDao.properties配置文件的信息读取到了 InputStream 流当中:
try {
InputStream inputStream =
MyBeanFacory.class.getClassLoader().getResourceAsStream("userDao.properties");
prop.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 创建了一个静态方法:
* 返回一个实例对象:
* @return
*/
public static Object getInstance() {
try {
// com.offcn.service.impl.UserServiceImpl
String value = prop.getProperty("userDao");
//使用反射:
Class aClass = Class.forName(value);
Object obj= aClass.newInstance();
// map.put()
return obj;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/* public static void main(String[] args) {
Object obj = getInstance();
System.out.println(obj);
}*/
}
总结: 当前案例代码的总结:
使用了 工厂模式+ 反射+ properties文件,进行了解耦合。 就类似于spring当中的applicationContext 工厂对象。
springIOC的底层原理:
applicationContext: 读取了applicationContext.xml配置文件:
Bean标签: xml 文件的解析: dom4J jdom jaxp解析器:
value: 全路径。
底层通过反射: —>反射对象。
创建创建来的对象存在一个容器当中:
spring整合jdbc模块
Spring当中提供在dao层提供了 JdbcTemplate模板对象。 该模板对象使用DbUtils框架使用基本一致。
引入依赖
<!--jdbc 依赖: tx包: 事务管理~ -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
核心配置文件当中配置
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--链接数据库的四大参数:-->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
<!--JdbcTemplate模板对象交给spring管理: -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
写操作
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
public class JdbcTemplateTest {
private JdbcTemplate jdbcTemplate ;
@Before
public void init(){
//第一步: 创建一个JdbcTemplate对象:
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
jdbcTemplate = (JdbcTemplate) context.getBean("jdbcTemplate");
}
@Test
public void test2(){
/*String sql ="insert into account(name,money) values(?,?)";
jdbcTemplate.update(sql,"ddd",999.9);*/
/* String sql ="update account set name =?, money=? where id=?";
jdbcTemplate.update(sql,"DDD",10000.0,1004);*/
String sql ="delete from account where id=?";
jdbcTemplate.update(sql,1004);
}
}
读操作
/*
根据id查询:
query方法返回的是一个list集合:
BeanPropertyRowMapper(); 结果集处理器的名称:
*/
@Test
public void test3(){
String sql ="select * from account where id =?";
List<Account> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Account>(Account.class),1001);
Account account = query.get(0);
System.out.println(account);
}
/*
查询列表:
*/
@Test
public void test4(){
String sql ="select * from account ";
List<Account> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Account>(Account.class));
System.out.println(query);
}
/**
* 自定义结果集处理器:
*/
@Test
public void test5(){
String sql ="select * from account ";
List<Account> query = jdbcTemplate.query(sql, new RowMapper<Account>() {
@Override
public Account mapRow(ResultSet resultSet, int i) throws SQLException {
//思路: 取出结果集 resultSet ----> Account对象当中:
Account account = new Account();
account.setId(resultSet.getInt("id"));
account.setName(resultSet.getString("name"));
account.setMoney(resultSet.getDouble("money"));
return account;
}
});
System.out.println(query);
}
@Test
public void test8(){
String sql ="select * from account where id =?";
Account account = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Account>(Account.class),1001);
System.out.println(account);
}