1 Spring(但愿这次能听懂记住)

文章详细介绍了Spring中BeanFactory和ApplicationContext的区别与联系,Bean的实例化方式,包括构造方法、静态构造方法、动态构造方法以及FactoryBean。还讨论了Bean的作用域,如singleton和prototype。此外,文章提到了Spring应用中的Bean生命周期,包括初始化过程、属性填充、三级缓存机制,以及Aware接口和注解驱动的配置。
摘要由CSDN通过智能技术生成

1 Spring

1.1 beanFactory和ApplicationContext

1.1 1beanFactory

BeanFactory 是字面意思是“Bean 工厂”,那么顾名思义“Bean 工厂”就是用来生产 Bean 或者是用来存放 Bean 的吗?
实际上 BeanFactory 是一个 Spring IoC 容器

使用beanFactory完成了ioc思想的实现,下面去实现一下Di依赖注入:

  1. 定义UserDao接口及其UserDaoImpl实现类
  2. 修改UserServiceImpl代码,添加一个setUserDao(UserDao userDao)用于接收注入对象
  3. 修改beans.xml配置文件,在UserDaoImpl的中嵌入配置注入;
  4. 修改测试代码,获得UserService时,setUserService方法执行注入操作
<bean id="userService" class="com.bjpowernode.impl.UserServiceImpl">
   <property name="userDao" ref="userDao"/>
</bean>
    <bean id="userDao"  class="com.bjpowernode.impl.UserDaoImpl"></bean>
</beans>
public class UserServiceImpl implements UserService {
    public void setUserDao(UserDao userDao){
        System.out.println("注入"+userDao);
    }
}
public class UserDaoImpl implements UserDao {
}
public class BeanFactory {
    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions("bean.xml");
        UserService userService = (UserService) beanFactory.getBean("userService");
        System.out.println(userService);
        UserDao userDao = (UserDao) beanFactory.getBean("userDao");
        System.out.println(userDao);
    }
}

1.1.2 ApplicatonContext

ApplicationContext成为Spring容器,内部封存了BeanFactor,比BeanFactor功能更丰富更强大,使用ApplicationContext进行开发时,xml配置文件的名称习惯写成applicationContext.xml

public class ApplicationContextTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext= new ClassPathXmlApplicationContext("bean.xml");
        UserService userService = (UserService) applicationContext.getBean("userService");
        System.out.println(userService);
    }
}

1.1.3 BeanFactory和ApplicationContext的关系

  1. BeanFactor是Spring的早期接口,成为Spring的bean工厂,ApplicationContext是后期更加高级的接口,成为Spring容器
  2. ApplicationContext在BeanFactor基础上对功能进行了扩展,例如:监听功能,国际化功能等。BeanFactory的API更偏向底层,ApplicationContext的API大多数是对这些底层API的封装
  3. Bean创建的主要逻辑和功能都被封装在BeanFactory,ApplicationContext不仅继承了BeanFactory,而且ApplicationContext内容还维护着BeanFactory的引用,所以,ApplicationContext与BeanFactor既有继承关系,又有融合关系
  4. Bean的初始化实际不同,原始BeanFactor是在首次调用getBean时才进行Bean的创建,而ApplicationContext则是配置文件加载,容器一创建就将Bean都实例化并初始化好

1.2 实例化bean的方式

1.2.1 构造方法实例化bean

 <bean id="bookDao" name="dao dao1 dao2 bookDao2" class="org.example.dao.impl.BookDaoImpl" scope="prototype" />
 public class App2 {
    public static void main(String[] args) {
//       方式一
        //3.获取IoC容器
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        //4.获取bean
        BookDao bookDao = (BookDao) ctx.getBean("bookDao");
        bookDao.save();
    }
}

1.2.2 静态构造方法实例化bean

 <bean id="orderDao" class="org.example.factory.OrderDaoFactory" factory-method="getOrderDao"/>
 public class OrderDaoFactory {
//    方式二:静态方法
    public static OrderDao getOrderDao(){
        return new OrderDaoimpl();
    }
}

1.2.3动态构造方法实例化bean

  <bean id="OrderDao" class="org.example.factory,OrderDaoFacyor" factory-bean="orderFactory" factory-method="getorderDao"/>
public class OrderDaoFactory {
 //    方式三:工厂实例化
    public OrderDao getorderDao(){
        return new OrderDaoimpl();
    }
}

1.2.4使用FactoryBean实例化bean

<bean id="orderdao" class="org.example.factory.OrderDaoFactoryBean"/>
 public class OrderDaoFactoryBean implements FactoryBean<OrderDao> { 
//    方式四:代替原始实例工厂中创建的方法
    public OrderDao getObject() throws Exception {
        return new OrderDaoimpl();
    }
    public Class<?> getObjectType() {
        return OrderDao.class;
    }
    //控制是否单例
    public boolean isSingleton() {
        return false;
    }
}

1.2.5 Bean的作用域

  1. singleton,每次注⼊只会创建⼀次

  2. prototype,每次注⼊都会创建⼀次

  3. request,每次请求都会创建⼀次

  4. session,每个session内只会创建⼀次,随着session过期

  5. global_session,全局session只会创建⼀次,随着全局session过期

1.3 Spring应用

1.3.1 Bean实例化的基本流程
  • 加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象
  • 将BeanDefinition存储在一个名为beanDefinitionMap的Map<String,BeanDefinition>
  • ApplicationContext底层遍历beanDefinitionMap,创建Bean实例对象
  • 创建好的Bean实例对象,被存到一个名为singletonObjects的Map<String,Object>中
  • 当执行applicationContext.getBean(beanName)时,从singletonObject去匹配Bean实例返回

1.3.2 工厂后处理器

Spring的后处理器是Spring对外开发的重要扩展点,允许我们介入Bean的整个实例化流程中来,以达到动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用.Spring主要有两种后处理器:

  • BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行;
  • BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObjects之前执行

1.3.3 BeanFactoryPostProcessor

BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器管理的话,那么Spring就会回调接口的方法,用于对BeanDefinition注册和修改的功能。
BeanFactoryPostProcessor定义如下

public interface BeanFactoryPostProcessor{
  void postProcessBeanFactor(ConfigurableListableBeanFactor beanFactor){
  }
}
//修改功能
public class MyBeanFactory implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("beanDefinitionMap填充完毕后回调该方法");
        //不会把整个map全部拿到 但是可以根据名字拿到map其中的数据
        BeanDefinition userService = beanFactory.getBeanDefinition("userService");
        userService.setBeanClassName("com.bjpowernode.UserDaoImpl");
    }
}
//bean的新增
public class MyBeanFactory implements BeanFactoryPostProcessor {
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("beanDefinitionMap填充完毕后回调该方法");
        //先创建一个beanDefinition对象
        BeanDefinition beanDefinition=new RootBeanDefinition();
        beanDefinition.setBeanClassName("com.bjpowernode.dao.UserServiceImpl");
        //DefaultListableBeanFactory是ConfigurableListableBeanFactory的一个子类 这样可以实现bean的新增
       DefaultListableBeanFactory defaultListableBeanFactory=(DefaultListableBeanFactory) beanDefinition;
       defaultListableBeanFactory.registerBeanDefinition("userServiceImpl",beanDefinition);
    }
}

1.3.4 BeanDefinitionRegistryPostProcessor

//BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor
public class ApplicationContextTest implements BeanDefinitionRegistryPostProcessor {
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        //先执行这个
        //注册新增bean对象
    }
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        //在执行这个
        //修改bean对象功能
    }
}

1.3.5 Bean后处理器-BeanPostProcessor

Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过Bean的初始化过程,例如:属性的填充,初始化方法init的执行等,其中有一个对外进行扩展的点BeanPostProcessor,我们称为Bean后处理.跟上面的Bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器的BeanPostProcessor,会在流程节点上被Spring自动调用

public class MyBeanPostProcessor implements BeanPostProcessor {
    //bean创建之前按
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
    //中间会有类的初始化方法
     //bean创建之后
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }
}

1.4 Spring Bean的生命周期

SpringBean的生命周期是从Bean实例化之后,即通过反射创建处对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为SpringBean的生命周期。Spring Bean的生命周期大体上分为三个阶段:

  • Bean的实例化阶段:Spring框架会取出BeanDefinition的信息进行判断当前Bean的范围是否是singleton的,是否不是延迟加载的,是否不是FactorBean等,最终将一个普通的singleton的Bean通过反射进行实例化;
  • bean的初始化阶段:Bean创建之后还仅仅是个"半成品",还需要对Bean实例的属性进行填充,执行一些Aware接口方法,执行BeanPostProcessor方法,执行InitializingBean接口的初始化方法,执行自定义初始化init方法等.该
  • Bean的完成阶段:经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池singletonObject中去了,即完成了Spring Bean的整个生命周期

1.4.1Spring Bean初始化过程

  • Bean实例的属性填充
  • Aware接口属性注入
  • BeanPostProcessor的before()方法回调
  • InitializingBean接口的初始化方法回调
  • 自定义初始化方法init回调
  • BeanPostProcessor的after()方法回调

1.4.2 Bean的属性填充

  • 注入普通属性,String,int或存储基本类型集合时,直接通过set方法的反射设置进去;
  • 注入单向对象引用属性时,从容器中getBean获取后通过set方法反射进去,如果容器中没有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作
  • 注入双向对象引用属性时,比较复杂

1.4.3 三级缓存

        //第1级缓存 用于存放 已经属性赋值、完成初始化的 单列BEAN
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
        //第2级缓存 用于存在已经实例化,还未做代理属性赋值操作的 单例BEAN
        private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
        //第3级缓存 存储创建单例BEAN的工厂
        private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)
  • UserService实例化对象,但尚未初始化,将UserService存储到三级缓存
  • UserService属性注入,需要UserDao,从缓存中获取,没有UserDao;
  • UserDao实例化对象,但尚未初始化,将UserDao存储到三级缓存
  • UserDao属性注入,需要UserService,从三级缓存获取UserService,UserService从三级缓存移入二级缓存
  • UserDao执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存
  • UserService注入UserDao
  • UserService执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存

1.3.4 常用的Aware接口

Aware接口是一种框架辅助属性注入一种思想,其他框架中也可以看到类似的接口.框架具备高度封装性,我们接触到的一个都是业务代码,一个底层功能API不能轻易的获取到,但是这不意味着永远用不到这些对象,如果用到了,就可以使用框架提供的类似Aware接口,让框架给我们注入该对象

总结

1.4 Spring注解

//@Component衍生注解 @Repository在dao层类上使用 @Service @Controller
@Component("userDao")
//作用范围注解
@Scope("singleton")
//拖延加载
@Lazy(false)
public class UserDaoImpl implements UserDao {
    public UserDaoImpl() {

    }
    //初始化方法注解
    @PostConstruct
    public void init(){
        System.out.println("userDao的初始化方法");
    }
    //销毁方法注解
    @PreDestroy
    public void destroy(){
        System.out.println("userDao的销毁方法");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值