httpservlert 的init 方法与initializingbean的afterpropertiesset有啥显微的区

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了httpservlert 的init 方法与initializingbean的afterpropertiesset有啥显微的区相关的知识,希望对你有一定的参考价值。

参考技术A Spirng的InitializingBean为bean提供了定义初始化方法的方式。InitializingBean是一个接口,它仅仅包含一个方法:afterPropertiesSet()。
Bean实现这个接口,在afterPropertiesSet()中编写初始化代码:
package research.spring.beanfactory.ch4; import org.springframework.beans.factory.InitializingBean; public class LifeCycleBean implements InitializingBean public void afterPropertiesSet() throws Exception System.out.println("LifeCycleBean initializing...");

在xml配置文件中并不需要对bean进行特殊的配置:
xml version="1.0" encoding="UTF-8"?>DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean name="lifeBean" class="research.spring.beanfactory.ch4.LifeCycleBean">
</bean>
</beans>

编写测试程序进行测试:
package research.spring.beanfactory.ch4; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; public class LifeCycleTest public static void main(String[] args) XmlBeanFactory factory=new XmlBeanFactory(new ClassPathResource("research/spring/beanfactory/ch4/context.xml")); factory.getBean("lifeBean");

运行上面的程序我们会看到:“LifeCycleBean initializing...”,这说明bean的afterPropertiesSet已经被Spring调用了。

Spring在设置完一个bean所有的合作者后,会检查bean是否实现了InitializingBean接口,如果实现就调用bean的afterPropertiesSet方法。
SHAPE /* MERGEFORMAT
装配bean的合作者
查看bean是否实现InitializingBean接口
调用afterPropertiesSet方法
init-method
Spring虽然可以通过InitializingBean完成一个bean初始化后对这个bean的回调,但是这种方式要求bean实现 InitializingBean接口。一但bean实现了InitializingBean接口,那么这个bean的代码就和Spring耦合到一起了。通常情况下我不鼓励bean直接实现InitializingBean,可以使用Spring提供的init-method的功能来执行一个bean 子定义的初始化方法。
写一个java class,这个类不实现任何Spring的接口。定义一个没有参数的方法init()。
package research.spring.beanfactory.ch4;
publicclass LifeCycleBean
publicvoid init()
System.out.println("LifeCycleBean.init...");



在Spring中配置这个bean:
xml version="1.0" encoding="UTF-8"?>DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd"><beans><bean name="lifeBean" class="research.spring.beanfactory.ch4.LifeCycleBean"
init-method="init">bean>beans>

当Spring实例化lifeBean时,你会在控制台上看到” LifeCycleBean.init...”。

Spring要求init-method是一个无参数的方法,如果init-method指定的方法中有参数,那么Spring将会抛出java.lang.NoSuchMethodException

init-method指定的方法可以是public、protected以及private的,并且方法也可以是final的。

init-method指定的方法可以是声明为抛出异常的,就像这样:
final protected void init() throws Exception
System.out.println("init method...");
if(true) throw new Exception("init exception");

如果在init-method方法中抛出了异常,那么Spring将中止这个Bean的后续处理,并且抛出一个org.springframework.beans.factory.BeanCreationException异常。

InitializingBean和init-method可以一起使用,Spring会先处理InitializingBean再处理init-method。
org.springframework.beans.factory.support. AbstractAutowireCapableBeanFactory完成一个Bean初始化方法的调用工作。 AbstractAutowireCapableBeanFactory是XmlBeanFactory的超类,再 AbstractAutowireCapableBeanFactory的invokeInitMethods方法中实现调用一个Bean初始化方法:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.java:
//……
//在一个bean的合作者设备完成后,执行一个bean的初始化方法。protectedvoid invokeInitMethods(String beanName, Object bean, RootBeanDefinition mergedBeanDefinition)
throws Throwable
//判断bean是否实现了InitializingBean接口if (bean instanceof InitializingBean)
if (logger.isDebugEnabled())
logger.debug("Invoking afterPropertiesSet() on bean with name '"+ beanName +"'");

//调用afterPropertiesSet方法
((InitializingBean) bean).afterPropertiesSet();

//判断bean是否定义了init-methodif(mergedBeanDefinition!=null&&mergedBeanDefinition.getInitMethodName() !=null)
//调用invokeCustomInitMethod方法来执行init-method定义的方法
invokeCustomInitMethod(beanName, bean, mergedBeanDefinition.getInitMethodName());

//执行一个bean定义的init-method方法protectedvoid invokeCustomInitMethod(String beanName, Object bean, String initMethodName)
throws Throwable
if (logger.isDebugEnabled())
logger.debug("Invoking custom init method '"+ initMethodName +"' on bean with name '"+ beanName +"'");

//使用方法名,反射Method对象
Method initMethod = BeanUtils.findMethod(bean.getClass(), initMethodName, null);
if (initMethod ==null)
thrownew NoSuchMethodException(
"Couldn't find an init method named '"+ initMethodName +"' on bean with name '"+ beanName +"'");

//判断方法是否是publicif (!Modifier.isPublic(initMethod.getModifiers()))
//设置accessible为true,可以访问private方法。 initMethod.setAccessible(true);

try
//反射执行这个方法
initMethod.invoke(bean, (Object[]) null);

catch (InvocationTargetException ex)
throw ex.getTargetException();

//………..

通过分析上面的源代码我们可以看到,init-method是通过反射执行的,而afterPropertiesSet是直接执行的。所以 afterPropertiesSet的执行效率比init-method要高,不过init-method消除了bean对Spring依赖。在实际使用时我推荐使用init-method。
需要注意的是Spring总是先处理bean定义的InitializingBean,然后才处理init-method。如果在Spirng处理InitializingBean时出错,那么Spring将直接抛出异常,不会再继续处理init-method。
如果一个bean被定义为非单例的,那么afterPropertiesSet和init-method在bean的每一个实例被创建时都会执行。单例 bean的afterPropertiesSet和init-method只在bean第一次被实例时调用一次。大多数情况下 afterPropertiesSet和init-method都应用在单例的bean上。

Objective-C学习笔记(二十二)——初始化方法init的重写与自己定义

      初学OC。对init这种方法不是非常了解。我们如今来分别对init方法进行重写以及自己定义,来加深对他的了解。

本样例也是用Person类来进行測试。

(一)重写init方法。

(1)在Person.h中声明init方法:

-(instancetype)init;

(2)在Person.m中声明成员变量。以及写一个打印成员变量的函数,而且重写init初始化方法:在重写的方法中。对成员变量进行了赋值。注意,这个init方法是无參数的方法。

{
    NSString *_peopleName;
    int _peopleAge;
}

-(void)show{

    NSLog(@"_peopleName = %@",_peopleName);
    NSLog(@"_peopleAge = %d",_peopleAge);

}

//重写初始化方法。
- (instancetype)init
{
    self = [super init];
    if (self) {
        [email protected]"Bob";
        _peopleAge=24;
    }
    return self;
}

(3)在main.m中调用该重写的init方法,并进行打印成员变量的值。

        People *people  = [[People alloc]init];
        [people show];
        

(4)输出结果例如以下:

技术分享


(5)结果分析,输出结果成功打印出我们在init方法定义时候对成员变量的赋值。

符合预期。我们成功实现了对init方法的重写。


(二)自己定义init方法。

(1)在重写的init方法中。我们发现一个问题,我们无法在main.m中实现对init的操作。也无法通过參数传值的方式实现对成员变量的赋值。

最致命的问题是无法在实例化一个对象的时候对他拥有的成员变量赋值。

所以我们最好自己定义init方法。

      首先在Person.h中声明自己定义init方法,參数包含peopleName,peopleName.

-(instancetype)initPeople: (NSString *) peopleName andAge: (int)peopleAge;

(2)在Person.m中实现init方法。使用传入的參数值对成员变量进行赋值:

-(instancetype)initPeople:(NSString *)peopleName andAge:(int)peopleAge{

    self = [super init];
    if (self) {
        _peopleName = peopleName;
        _peopleAge = peopleAge;
    }
    return self;
}

(3)在main.m中实例化对象,在实例化对象的同一时候进行成员变量的赋值,然后信息打印:

People *people2 = [[People alloc]initPeople:@"Jack" andAge:26];

[people2 show];

(4)输出结果:

技术分享


(5)结果分析,我们成功在实例化对象的时候并对其赋值,这个就是初始化方法的作用。比最初的重写init方法更为灵活。

这就和C++中的构造方法起到类似的作用。


github主页:https://github.com/chenyufeng1991  。欢迎大家訪问!












以上是关于httpservlert 的init 方法与initializingbean的afterpropertiesset有啥显微的区的主要内容,如果未能解决你的问题,请参考以下文章

yii2.0高级框架配置时打开init.bat秒退的解决方法 (两种方法)

ini 用于在引导时挂载ChrUbuntu分区(#7 / ROOT-C)的Chromebook init脚本。

pytest-18-配置文件pytest.ini

十魔法方法特性和迭代器

mysql配置文件编码修改失败

内置方法 常用模块