Spring
Spring 中的IOC(控制反转)
以前创建对象都是通过new的形式来创建的,比如在项目中,Controller层需要Service的对象,需要在Controller中new出来使用才行,但是,随着业务的增加,Controller也随之对了起来,相对应的Service也new的越来越多,有时候控制不当,甚至每个方法里面都要new一个,这样会导致代码内存中对于Service的对象就有很多,出现两个缺点:1,Service的对象很多,占内存;2,代码不简洁,到处都是new的Service的对象;
IOC就是针对这俩问题的,相当于Spring提供了一个容器,这个容器专门用来放实例化的对象,比如之前的Service的对象,在这个容器中,要用的时候就去里面取出来就行,不用再自己去new,而且Spring对于这些实例化对象的Bean默认都是单例创建的,多以每个类的对象只能存在一个,不会占内存。
所以IOC,控制反转,就是将我们创建对象的控制权,交给了Spring,由Spring来统一管理。
Spring 中实例化Bean的方式(三种,也可以是4种)
1,构造方法实例化(无参构造),此处就算无参构造方法是private,私有的,也会成功创建Bean,说明能访问到类中的私有构造方法,显而易见Spring底层用的是反射,如果没有无参构造,直接报错,创建Bean失败,异常:Caused by: java.lang.NoSuchMethodException
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
获取Bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
2,静态工程实例化
//静态工厂创建对象
public class OrderDaoFactory {
public static OrderDao getOrderDao(){
System.out.println("factory setup....");//模拟必要的业务操作
return new OrderDaoImpl();
}
}
//通过静态工厂创建对象
OrderDao orderDao = OrderDaoFactory.getOrderDao();
如何交个Spring来管理呢?
<bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>
- class:工厂类的类全名
- factory-mehod:具体工厂类中创建对象的方法名
获取Bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
OrderDao orderDao = (OrderDao) ctx.getBean("orderDao");
3,实例工厂
这么一看,似乎和静态实例工厂模式没啥区别,无非就是将方法换成了非静态的而已:
public class UserDaoFactory {
public UserDao getUserDao(){
return new UserDaoImpl();
}
}
如何交给Spring来管理呢?
<bean id="userFactory" class="com.itheima.factory.UserDaoFactory"/>
<bean id="userDao" factory-method="getUserDao" factory-bean="userFactory"/>
- factory-bean:工厂的实例对象
- factory-method:工厂对象中的具体创建对象的方法名
获取Bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao) ctx.getBean("userDao");
4,FactoryBean
- 创建一个UserDaoFactoryBean的类,实现FactoryBean接口,重写接口的方法
public class UserDaoFactoryBean implements FactoryBean<UserDao> {
//代替原始实例工厂中创建对象的方法
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
//返回所创建类的Class对象
public Class<?> getObjectType() {
return UserDao.class;
}
}
- 在Spring的配置文件中进行配置
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
获取Bean
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao1 = (UserDao) ctx.getBean("userDao");
这种方式在Spring去整合其他框架的时候会被用到
FactoryBean接口其实会有三个方法,分别是:
T getObject() throws Exception;
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
方法一:getObject(),被重写后,在方法中进行对象的创建并返回
方法二:getObjectType(),被重写后,主要返回的是被创建类的Class对象
方法三:没有被重写,因为它已经给了默认值,从方法名中可以看出其作用是设置对象是否为单例,默认true。
Bean的生命周期
1.生命周期
从对象创建到对象销毁的过程
2. bean生命周期
- 通过构造器创建bean实例(默认无参数构造)
- 为bean的属性设置值和对其他bean引用(调用set方法)
- 把bean实例传递给bean前置处理器的方法postProcessBeforeInitialization
- 调用bean的初始化方法
- 把bean实例传递给bean后置处理器的方法postProcessAfterInitialization
- 获取bean实例对象
- 当容器关闭时候,调用bean的销毁方法
3.演示bean生命周期
创建Order类
public class Order {
String name;
public Order() {
System.out.println("第一步:调用无参构造方法");
}
public void setName(String name) {
this.name = name;
System.out.println("第二步:调用set方法");
}
public void add(){
System.out.println("第四步:调用初始化方法");
}
public void sub(){
System.out.println("第七步:调用销毁方法");
}
}
实现BeanPostProcessor接口
public class MybeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第三步:调用before方法");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("第五步:调用After方法");
return null;
}
}
创建配置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 id="order" class="com.github.entity.Order" init-method="add" destroy-method="sub">
<property name="name" value="订单"></property>
</bean>
<bean id="mybeanPost" class="com.github.entity.MybeanPost"></bean>
</beans>
编写测试类
public class OrderTest {
@Test
public void test(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");
Order order = context.getBean("order",Order.class);
System.out.println("第六步:获取实例对象");
context.close();
}
}
Spring中的DI(依赖注入)
在实际开发过程中,可能会存在这种情况,比如一个Controller中,需要某些Service的对象,我们需要将Service的对象注入到Controller中,这就叫做依赖注入,简单来讲就是绑定Spring IOC容器中的各个Bean的关系,建立对象与对象之间的绑定关系,这就叫做依赖注入。
Spring中的AOP(面向切面编程)