1.Spring IOC
Inverse of Control,控制反转
简单的说就是引入工厂(第三者),将原来在程序中手动创建的对象,交给工厂来创建管理。
1.1 理解工厂的作用
// 实现一个简单的通过工厂获取对象的方式
public class Factory {
//提供获取对象的方法
public UserDAOImpl getUserDAO(){
//返回实例对象
return new UserDAOImpl ();
}
}
缺点:工厂方法仍然需要返回具体类型的实例对象,存在代码耦合,一个工厂只能获取单一类型的对象,
解决方案:
使用反射技术传入具体类型的类字符串生产对象的实例:
public class Factory {
//利用反射技术生产具体类型的实例对象
public Object getBean(){
Object bean = null;
try {
//传入类字符串,生产对象实例
bean = Class.forName("cn.itcast.spring.a_quickstart.UserDAOImpl").newInstance();
} catch (Exception e) {
e.printStackTrace();
}
//返回具体类型的对象类型实例
return bean;
}
}
public static void main(String[] args) {
//使用反射方法获取对象
IUserDAO userDAO = (IUserDAO) userDAOFactory.getBean();
userDAO.findUserByUsernameAndPassword();
}
发现问题:类字符串是固定的,怎么动态的传入不同的类字符串呢?
解决方案:
使用xml配置文件动态传入类字符串
IoC底层实现:工厂(设计模式)+反射(机制) + 配置文件(xml)。
- 工厂:spring容器
- 配置文件(xml):applicationContext.xml
- 反射:每一个bean要配置class(对象类型的类字符串)
applicationContext.xml:
<?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: spring工厂创建的一个对象(反射机制)
id/name:对象的名字,可以用来引用或者获取对象, 一般为类名或接口名称的首字母小写
class:要创建的对象类型的类字符串,类名全路径
-->
<bean id="userDAO" class="cn.itcast.spring.a_quickstart.UserDAOImpl" />
</beans>
public static void main(String[] args) {
//spring配置方式,创建spring工厂,加载spring配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
//从spring工厂中获取对象,通过bean的id/name
IUserDAO userDAO = (IUserDAO) ac.getBean("userDAO");
userDAO.findUserByUsernameAndPassword();
}
2.DI注入
DI:Dependency Injection 依赖注入,在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件(简单的说,可以将另外一个bean对象动态的注入到另外一个bean中。)
Di的做法是:由Spring容器创建了Service、Dao对象,并且在配置中将Dao传入Servcie,那么Service对象就包含了Dao对象的引用。
步骤一:将service对象和dao对象交给spring容器管理
applicationContext.xml:
<?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: spring工厂创建的一个对象(反射机制)
id/name:对象的名字,可以用来引用或者获取对象, 一般为类名或接口名称的首字母小写
class:要创建的对象类型的类字符串,类名全路径
-->
<bean id="userDAO" class="cn.itcast.spring.a_quickstart.UserDAOImpl" />
<bean id ="userService" class="cn.itcast.spring.a_quickstart.UserServiceImpl">
<!-- 注入对象 -->
<!-- property 根据类中的setter方法进行属性注入 -->
<!-- name:setter方法的后缀小写,比如setXxx 对应的name为xxx -->
<!-- ref:引用哪一个bean(对象),值为bean的id/name -->
<property name="userDAO" ref="userDAO" />
</bean>
</beans>
步骤二:在sevice中定义属性提供setter方法:
public class UserServiceImpl implements IUserService{
//定义属性
private IUserDAO userDAO;
public void setUserDAO(IUserDAO userDAO) {
this.userDAO = userDAO;
}
public void login() {
System.out.println("UserServiceImpl-service层方法调用了");
//ioc:依赖注入
userDAO.findUserByUsernameAndPassword();
}
}
步骤三:测试运行,此时获取对象必须从spring工厂获取(在spring容器配置中才有依赖注入,自己创建的对象没有注入依赖关系)
public class SpringTest {
//测试
@Test
public void test(){
//创建service的示例
//IUserService userService = new UserServiceImpl();
//userService.login();
//创建spring工厂,获取spring管理的对象
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
IUserService userService = (IUserService) ac.getBean("userService");
userService.login();
}
}
3.后处理Bean(BeanPostProcessor接口)
后处理Bean也称之为Bean的后处理器,作用是:在Bean初始化的前后,对Bean对象进行增强。它既可以增强一个指定的Bean,也可以增强所有的Bean,底层很多功能(如AOP等)的实现都是基于它的,Spring可以在容器中直接识别调用。