当前位置: 首页 > news >正文

如何提升网站的排名网站开发项目成本分析之合理性

如何提升网站的排名,网站开发项目成本分析之合理性,自贡北京网站建设,网站建设最新新闻所谓万物皆对象,对于一个 bean 而言,从出生到死亡,他要经历哪些阶段呢? 生命周期 理解对象的生命周期,可以帮助我们更好的做一些扩展。 一个对象从被创建到被垃圾回收,可以大致分为这 5 个阶段&#xff1a…

所谓万物皆对象,对于一个 bean 而言,从出生到死亡,他要经历哪些阶段呢?

生命周期

理解对象的生命周期,可以帮助我们更好的做一些扩展。

在这里插入图片描述

一个对象从被创建到被垃圾回收,可以大致分为这 5 个阶段:

  1. 创建/实例化阶段:调用类的构造方法,产生一个新对象;
  2. 初始化阶段:此时对象已经被创建了,但还未被正常使用,可以在这里做一些初始化的操作;
  3. 运行使用期:此时对象已经完全初始化好,程序正常运行,对象被使用;
  4. 销毁阶段:此时对象准备被销毁,需要预先的把自身占用的资源等处理好(如关闭、释放数据库连接);
  5. 回收阶段:此时对象已经完全没有被引用了,被垃圾回收器回收。

理解了一个 Bean 的生命周期后,下面我们看下SpringFramework怎么对Bean 的生命周期做干预的。

单实例 Bean 的生命周期

init-method & destroy-method

1)创建 Bean

package com.study.spring.a_initmethod;public class Cat {private String name;public Cat() {System.out.println("Cat 构造方法执行了。。。");}public void setName(String name) {System.out.println("setName方法执行了。。。");this.name = name;}public void init() {System.out.println(name + " 被初始化了。。。");}public void destroy() {System.out.println(name + " 被销毁了。。。");}
}public class Dog {private String name;public Dog() {System.out.println("Dog 构造方法执行了。。。");}public void setName(String name) {System.out.println("setName方法执行了。。。");this.name = name;}public void init() {System.out.println(name + "被初始化了。。。");}public void destroy() {System.out.println(name + "被销毁了。。。");}
}

2)分别创建 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/beanshttps://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.study.spring.a_initmethod.Cat" init-method="init" destroy-method="destroy"><property name="name" value="小米米"/></bean>
</beans>
@Configuration
public class Config {@Bean(initMethod = "init",destroyMethod = "destroy")public Dog dog(){Dog dog = new Dog();dog.setName("小勾勾");return dog;}
}

3)分别测试xml 和注解驱动

private static void testXml() {System.out.println("准备初始化IOC容器。。。");ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean-initmethod.xml");System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");context.close();System.out.println("IOC容器销毁完成。。。");}private static void testAnnotationConfig() {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");applicationContext.close();System.out.println("IOC容器销毁完成。。。");}

输出如下:

准备初始化IOC容器。。。
Cat 构造方法执行了。。。
setName方法执行了。。。
小米米 被初始化了。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
小米米 被销毁了。。。
IOC容器销毁完成。。。-----------------------------准备初始化IOC容器。。。
Dog 构造方法执行了。。。
setName方法执行了。。。
小勾勾被初始化了。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
小勾勾被销毁了。。。
IOC容器销毁完成。。。

由此可以得出结论:在 IOC 容器初始化之前,默认情况下 Bean 已经创建好了,而且完成了初始化动作;容器调用销毁动作时,先销毁所有 Bean ,最后 IOC 容器全部销毁完成。

同时也可以看出来,在 Bean 的生命周期中,是先对属性赋值,后执行 init-method 标记的方法。

@PostConstruct & @PreDestroy

上面的 Cat 和 Dog 都是我们手动声明注册的,但是对于那些使用模式注解的 Bean ,这种方式就不好使了,因为没有可以声明 init-methoddestroy-method 的地方了。

此时可以使用JSR250 规范提供的 @PostConstruct@PreDestroy 这两个注解,分别对应 init-methoddestroy-method

比如,Spring中常用的模式注解:@Component、@Service、@Repository、@Controller,使用这些注解,Spring容器可以在启动时自动扫描并注册这些Bean,而不需要显式地在XML配置文件中声明或在Java配置类中手动注册。

1)创建Bean

@Component
public class Pen {private Integer ink;public Pen(){System.out.println("钢笔的构造方法");}@PostConstructpublic void addInk() {System.out.println("钢笔中已加满墨水。。。");this.ink = 100;}@PreDestroypublic void outWellInk() {System.out.println("钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}
}

2)测试

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.study.spring.b_jsr250");System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");ctx.close();System.out.println("IOC容器销毁完成。。。");}
}

输出如下:

准备初始化IOC容器。。。
钢笔的构造方法
钢笔中已加满墨水。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
钢笔中的墨水都放干净了。。。
IOC容器销毁完成。。。

可以得出结论:这两个注解实现的效果和 init-methoddestroy-method 是一样的。

JSR250规范 与 init-method 共存

如果 @PostConstruct@PreDestroyinit-methoddestroy-method 共存,执行顺序是怎样的呢?

1)创建 Bean

public class Pen {private Integer ink;public Pen(){System.out.println("钢笔的构造方法");}public void open() {System.out.println("init method ...打开钢笔");}public void close() {System.out.println("destroy-method - 合上钢笔。。。");}@PostConstructpublic void addInk() {System.out.println("@PostConstruct...钢笔中已加满墨水。。。");this.ink = 100;}@PreDestroypublic void outWellInk() {System.out.println("@PreDestroy...钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}
}

2)创建配置类

@Configuration
public class JSR250Configuration {@Bean(initMethod = "open",destroyMethod = "close")public Pen pen() {return new Pen();}
}

3)测试执行

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(JSR250Configuration.class);System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");applicationContext.close();System.out.println("IOC容器销毁完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
钢笔的构造方法
@PostConstruct...钢笔中已加满墨水。。。
init method ...打开钢笔
IOC容器初始化完成。。。准备销毁IOC容器。。。
@PreDestroy...钢笔中的墨水都放干净了。。。
destroy-method - 合上钢笔。。。
IOC容器销毁完成。。。

可以得出结论:JSR250 规范的执行优先级高于 init / destroy。

InitializingBean & DisposableBean

是 SpringFramework 内部预先定义好的两个关于生命周期的接口,他们的触发时机与 init-method & destroy-method@PostConstruct @PreDestroy一样,都是在 Bean 的初始化和销毁阶段要回调的。

1)创建 Bean

@Component
public class Pen implements InitializingBean, DisposableBean {private Integer ink;@Overridepublic void destroy() throws Exception {System.out.println("钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("钢笔中已加满墨水。。。");this.ink = 100;}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}
}

2)测试执行

public class InitializingDisposableAnnoApplication {public static void main(String[] args) throws Exception {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.study.spring.c_initializingbean");System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");ctx.close();System.out.println("IOC容器销毁完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
钢笔中已加满墨水。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
钢笔中的墨水都放干净了。。。
IOC容器销毁完成。。。

三种生命周期并存

当一个 Bean 同时用这三种生命周期控制时,执行顺序又是怎么样的呢?

1)创建 Bean

@Component
public class Pen implements InitializingBean, DisposableBean {private Integer ink;public Pen(){System.out.println("构造方法");}public void open() {System.out.println("init-method - 打开钢笔。。。");}public void close() {System.out.println("destroy-method - 合上钢笔。。。");}@PostConstructpublic void addInk() {System.out.println("@PostConstruct 钢笔中已加满墨水。。。");this.ink = 100;}@PreDestroypublic void outwellInk() {System.out.println("@PreDestroy 钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic void destroy() throws Exception {System.out.println("DisposableBean - 写完字了。。。");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean - 准备写字。。。");}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}}

2)创建配置类

@Configuration
public class Config {@Bean(initMethod = "open",destroyMethod = "close")public Pen pen(){return new Pen();}
}

3)测试执行

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");System.out.println();System.out.println("准备销毁IOC容器。。。");ctx.close();System.out.println("IOC容器销毁完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
构造方法
@PostConstruct 钢笔中已加满墨水。。。
InitializingBean - 准备写字。。。
init-method - 打开钢笔。。。
IOC容器初始化完成。。。准备销毁IOC容器。。。
@PreDestroy 钢笔中的墨水都放干净了。。。
DisposableBean - 写完字了。。。
destroy-method - 合上钢笔。。。
IOC容器销毁完成。。。

可以看到执行顺序是:@PostConstruct → InitializingBean → init-method

原型Bean的生命周期

当面介绍的都是单实例 Bean 的生命周期,而对于原型 Bean,它与单实例 Bean 的生命周期是不一样的。

单实例 Bean 的生命周期是陪着 IOC 容器一起的,容器初始化,单实例 Bean 也跟着初始化(延迟 Bean 例外);
容器销毁,单实例 Bean 也跟着销毁。
原型 Bean 由于每次都是取的时候才产生一个,所以它的生命周期与 IOC 容器无关。

1)创建 Bean

@Component
public class Pen implements InitializingBean, DisposableBean {private Integer ink;public Pen(){System.out.println("构造方法");}public void open() {System.out.println("init-method - 打开钢笔。。。");}public void close() {System.out.println("destroy-method - 合上钢笔。。。");}@PostConstructpublic void addInk() {System.out.println("@PostConstruct 钢笔中已加满墨水。。。");this.ink = 100;}@PreDestroypublic void outWellInk() {System.out.println("@PreDestroy 钢笔中的墨水都放干净了。。。");this.ink = 0;}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean - 准备写字。。。");}@Overridepublic void destroy() throws Exception {System.out.println("DisposableBean - 写完字了。。。");}@Overridepublic String toString() {return "Pen{" + "ink=" + ink + '}';}
}

2)创建配置类

@Configuration
public class Config {@Bean(initMethod = "open",destroyMethod = "close")@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) //原型Beanpublic Pen pen(){return new Pen();}
}

3)测试执行

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
IOC容器初始化完成。。。

由此得出结论:原型 Bean 的创建不随 IOC 的初始化而创建。

然后,在main 方法中去获取该 Bean,再次执行:

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");System.out.println("准备获取pen");Pen pen = ctx.getBean(Pen.class);System.out.println("获取到pen");}
}

输出结果:

准备初始化IOC容器。。。
IOC容器初始化完成。。。
准备获取pen
构造方法
@PostConstruct 钢笔中已加满墨水。。。
InitializingBean - 准备写字。。。
init-method - 打开钢笔。。。
获取到pen

由此得出结论:原型Bean的初始化动作与单实例Bean完全一致。

接着,我们把销毁 Bean 的代码也加上:

public class Client {public static void main(String[] args) {System.out.println("准备初始化IOC容器。。。");AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);System.out.println("IOC容器初始化完成。。。");System.out.println("准备获取pen");Pen pen = ctx.getBean(Pen.class);System.out.println("获取到pen");System.out.println("用完Pen了,准备销毁。。。");ctx.getBeanFactory().destroyBean(pen);System.out.println("Pen销毁完成。。。");}
}

输出结果:

准备初始化IOC容器。。。
IOC容器初始化完成。。。
准备获取pen
构造方法
@PostConstruct 钢笔中已加满墨水。。。
InitializingBean - 准备写字。。。
init-method - 打开钢笔。。。
获取到pen
用完Pen了,准备销毁。。。
@PreDestroy 钢笔中的墨水都放干净了。。。
DisposableBean - 写完字了。。。
Pen销毁完成。。。

由此得出结论;原型 Bean 在销毁时不处理 destroyMethod 标注的方法


后置处理器 BeanPostProcessor

BeanPostProcessor 是一个容器的扩展点,它可以在 bean 的生命周期过程中,初始化阶段前后添加自定义处理逻辑,并且不同 IOC 容器间的 BeanPostProcessor 不会相互干预。
也可以配置多个BeanPostProcessor实例,通过设置order属性来控制BeanPostProcessor实例的执行顺序。

1)创建 bean

public class Dog implements InitializingBean {public void initMethod() {System.out.println("initMethod ...");}@PostConstructpublic void postConstruct() {System.out.println("@PostConstruct ...");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("InitializingBean ...");}
}

2)创建配置类

@Configuration
public class Config {@Bean(initMethod = "initMethod")public Dog dog() {return new Dog();}
}

3)创建两个后置处理器

@Component
public class InstantiationTracingBeanPostProcessor1 implements BeanPostProcessor, Ordered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Dog) {System.out.println("【第一个后置处理器】拦截到Bean的初始化之前:" + bean);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Dog) {System.out.println("【第一个后置处理器】拦截到Bean的初始化之后:" + bean);}return bean;}@Overridepublic int getOrder() {return 1;}
}
@Component
public class InstantiationTracingBeanPostProcessor2 implements BeanPostProcessor, Ordered {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Dog) {System.out.println("【第二个后置处理器】拦截到Bean的初始化之前:" + bean);}return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof Dog) {System.out.println("【第二个后置处理器】拦截到Bean的初始化之后:" + bean);}return bean;}@Overridepublic int getOrder() {return 2;}
}

4)测试执行

public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext("com.study.spring.postprocessor");}
}

输出结果:

【第一个后置处理器】拦截到Bean的初始化之前:com.study.spring.postprocessor.Dog@7f9fcf7f
【第二个后置处理器】拦截到Bean的初始化之前:com.study.spring.postprocessor.Dog@7f9fcf7f
@PostConstruct ...
InitializingBean ...
initMethod ...
【第一个后置处理器】拦截到Bean的初始化之后:com.study.spring.postprocessor.Dog@7f9fcf7f
【第二个后置处理器】拦截到Bean的初始化之后:com.study.spring.postprocessor.Dog@7f9fcf7f

由此得出 bean 的初始化阶段的全流程:BeanPostProcessor#postProcessBeforeInitialization → @PostConstruct → InitializingBean → init-method → BeanPostProcessor#postProcessAfterInitialization

参考资料:《从 0 开始深入学习Spring小册》

http://www.yayakq.cn/news/401751/

相关文章:

  • 免费手机版网站建设前端做网站一般用什么框架
  • 百度企业网站建设域名访问网址
  • 扶风网站建设天津设计公司排行榜
  • 做推广的装修网站seo优化员
  • 网络设计网站建设类网站模板昆明网站建设锐网
  • 做网站需要准备什么条件三门峡企业网站建设公司
  • 深圳品牌学校网站建设用div做网站代码
  • 做微信商城网站公司网页游戏浏览器
  • wordpress微信分享插件徐州企业网站排名优化
  • 北京响应式的网站做淘宝客必须要有网站吗
  • 国内好的网站设计高德地图在英国可以用吗
  • 怎么做微信辅助的网站国内网站赏析
  • 昆明 网站搭建企业解决方案架构
  • 图书馆网站信息化建设如何在网站插做视频
  • 做企业网站注意中山商城网站建设
  • 网站建设公司-跨界鱼科技优小城镇建设网站并阐述观点
  • 网站建设优化价格营销网名
  • .net如何做网站郑州网站设计制作
  • 广东网站建设人员网站建设需要什么材料
  • 帮做动态头像的网站企业营销微网站建设
  • 网站换空间上怎么办啊沈阳德泰诺网站建设
  • 南京工程建设招聘信息网站优秀seo平台
  • 罗田网站建设石家庄网站建设方案咨询
  • 提交网站给百度国外优秀的html5网站
  • 网站建设唐山赣州章贡区天气预报
  • 微信营销网站wordpress 5 开发
  • 对网站建设在电子商务中的看法企业百度推广怎么收费
  • 英文网站网站建设wordpress外贸网站源码
  • 自己开发网站怎么开发漯河企业网站开发
  • 哪些人可以做网站游戏分销代理平台