FactoryBean的应用实战
- 需要写一个A类来实现FactoryBean
- 实现FactoryBean的3个方法,即getOject(), getObjectType(), isSingleton()
- 注意:在通过xml的【 】标签或者通过注解方式将A类注入容器的时候,返回的实例不是A类,而是T类,因为他会自动的执行getObject()方法,而getObject()方法中new的是T类的对象,所以这块不要搞错了
- 下面代码案例: 有xml配置可见,bean注入的是MyFactoryBean, 但图中可以看出实例出来的却是ObjectBean类型的,
implements FactoryBean代码:
package com.spring.factoryBean实战;
import org.springframework.beans.factory.FactoryBean;
public class myFactoryBean implements FactoryBean<ObjectBean> {
@Override
public ObjectBean getObject() throws Exception {
return new ObjectBean("hbz", 26);
}
@Override
public Class<?> getObjectType() {
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 = "myFactoryBean" class="com.spring.factoryBean实战.myFactoryBean"></bean>
</beans>
BeanFactroyPostProcessor的应用实战
- BeanFactroyPostProcessor 会在 BeanPostProcessor之前执行, 即先执行BeanFactroyPostProcessor
- 作用:读取应用程序上下文,并对其属性进行修改, 可以修改BeanDefinition中的属性,比如设置单例多例(setScope), 是否是懒加载(setLazyInit()), 动态设置初始化方法等
- 执行BeanFactroyPostProcessor时还没有进行指定类的初始化(还未执行构造函数),所以通过BeanFactroyPostProcessor可以改变目标类属性
- 代码实战:
FactoryBeanPostPorcess代码:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFacotryPostProcess implements BeanFactoryPostProcessor {
public MyBeanFacotryPostProcess() {
System.out.println("构造函数执行--------------------------");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
// 获取所有的bean
String[] beanDefinitionNames = configurableListableBeanFactory.getBeanDefinitionNames();
for(String befinitonName : beanDefinitionNames){
if("productService".equalsIgnoreCase(befinitonName)){
BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(befinitonName);
// 单例多例
beanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
// 设置初始化方法
beanDefinition.setInitMethodName("testInit");
}
}
}
}
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 = "productService" class="com.spring.beanFactoryPostProcess实战.ProductServiceImpl" scope="singleton"></bean>
<!-- 这句需要加,表示启动的时候就注入到spring容器并运行一次, 这个类中就是设置ProductServiceImpl的属性的, 如果不写,那么动态配置的类属性是不会生效的-->
<bean id = "myBeanFacotryPostProcess" class="com.spring.beanFactoryPostProcess实战.MyBeanFacotryPostProcess"></bean>
</beans>
目标类代码:
package com.spring.beanFactoryPostProcess实战;
public class ProductServiceImpl implements ProductService{
public ProductServiceImpl(){
System.out.println("这个是构造函数");
}
@Override
public void example() {
System.out.println("类名: "+ this.getClass().toString());
}
public void testInit(){
System.out.println("这个是初始化方法");
}
}
输出结果:
BeanPostProcessor的应用
- BeanPostProcessor在BeanFactoryPostProcessor之后执行
- BeanPostProcessor作用于bean实例化过程中, 可以改变bean实例中的属性值, 比如bean中有个name = “123”, 则可以在BeanPostProcessor的两个实现方法中将其改成setName(“456”)
- BeanPostProcessor通常需要实现两个方法,分别是postProcessBeforeInitialization, postProcessAfterInitialization
- postProcessBeforeInitialization: 在目标类的【初始化方法】之前执行。postProcessAfterInitialization:在目标类【初始化方法之后】执行
- postProcessBeforeInitialization,postProcessAfterInitialization都会有个参数,叫【String beanName】, 这个beanName是容器中所有的bean(即容器有多少个bean,这俩方法就走多少遍),如果想在指定目标类触发BeanPostProcessor,则需要加一个判断。如果在xml定义了bean,则使用xml中定义的name去和beanName作比较,如果不是在xml中定义的,是new出来的,直接用目标类的【类名(首字母小写)】去和beanName比较,默认new出来的beanName就等于类名首字母小写
- 代码:
BeanPostProcessor实现类:
package com.spring.beanPostProcessor实战;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
/**
* 在每个bean初始化方法之前执行
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor # BeforeInitialization 调用 beanName = " + beanName);
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
/**
* 在每个bean初始化方法之后执行
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor # AfterInitialization 调用 beanName = " + beanName);
// 判断beanName,如果beanName = productBeanService, 则就执行如下操作
if("productBeanService".equalsIgnoreCase(beanName)){
ProductBeanServiceImpl productBeanService = (ProductBeanServiceImpl) bean;
productBeanService.setName("v2.修改后的值");
BeanPostProcessor.super.postProcessAfterInitialization(productBeanService, beanName);
}
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
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 = "productBeanService" class="com.spring.beanPostProcessor实战.ProductBeanServiceImpl" scope="singleton" init-method="testInit"></bean>
<bean id = "myBeanPostProcessor" class="com.spring.beanPostProcessor实战.MyBeanPostProcessor"></bean>
</beans>
目标类代码:
package com.spring.beanPostProcessor实战;
import org.springframework.beans.factory.InitializingBean;
/**
* 实现InitializingBean就可以实现初始化方法,因为InitializingBean中的afterPropertiesSet就是初始化方法,无需通过xml指定
*/
public class ProductBeanServiceImpl implements ProductBeanService, InitializingBean {
private String name = "v1.修改之前的值";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ProductBeanServiceImpl(){
System.out.println("这个是构造函数");
}
@Override
public void example() {
System.out.println("类名: "+ this.getClass().toString());
}
/**
* BeanPostProcessor中的postProcessBeforeInitialization方法会在该初始化方法之前执行
* BeanPostProcessor中的postProcessAfterInitialization方法会在该初始化方法之后执行
*
*/
public void testInit(){
System.out.println("这是在xml或者BeanFactoryPostProcess中指定的初始化方法");
}
/**
* 这个也是初始化方法,但必须实现InitializingBean
* 效果: 和testInit()一摸一样,该方法不需要在xml中配置,而testInit需要在xml或者通过BeanFactoryPostProcess配置并指定testInit初始化方法才可以
*
*
* BeanPostProcessor中的postProcessBeforeInitialization方法会在该初始化方法之前执行
* BeanPostProcessor中的postProcessAfterInitialization方法会在该初始化方法之后执行
* @throws Exception
*/
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("这是InitializingBean的初始化方法");
}
}
启动类代码:
package com.spring.beanPostProcessor实战;
import com.spring.beanFactoryPostProcess实战.ProductServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
// 读取指定的配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:beanPostPorcessor.xml");
ProductBeanServiceImpl productBeanService = (ProductBeanServiceImpl) context.getBean("productBeanService");
System.out.println(productBeanService);
}
}
执行结果截图:
文章评论