-
实例化前
为啥需要实例化前这个动作呢?在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。怎么理解实例化前?实例化,也就是new一个对象,实例化前,也就是在new对象之前执行。@Component public class MyPostProcess implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if ("other1Entity".equals(beanName)){ System.out.println("实例化前可以做一些操作,比如往redis设值,等等"); } return null; }
如上代码会导致,在other1Entity这个Bean实例化前,会进行打印。
值得注意的是,postProcessBeforeInstantiation()是有返回值的,如果这么实现:
@Component public class MyPostProcess implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if ("other1Entity".equals(beanName)){ System.out.println("实例化前可以做一些操作,比如往redis设值,等等"); return new Other1Entity(); } return null; } }
other1Entity这个Bean,在实例化前会直接返回一个由我们所定义的Other1Entity对象。如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。怎么验证这句话的真实性呢?请看以下代码:
@Component public class MyPostProcess implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if ("other1Entity".equals(beanName)){ System.out.println("实例化前可以做一些操作,比如往redis设值,等等"); return new Other1Entity(); } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { System.out.println("这是实例化后的操作,在这里面,对other1Entity的Name属性进行了赋值,但是并没有成功设置值"); if ("other1Entity".equals(beanName)){ Other1Entity o = (Other1Entity)bean; o.setName("yzyyzyzyzyzy"); System.out.println("postProcessAfterInstantiation:" + beanName); } return false; } }
可以看到,在实例化后的操作里面,对other1Entity的Name属性进行了赋值,但是并没有成功设置值。也就验证了那句话。 -
实例化
在这个步骤中就会根据BeanDefinition去创建一个对象了。
2.1. 通过Supplier创建对象。请看代码:@Component public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition)beanFactory.getBeanDefinition("other2Entity"); beanDefinition.setInstanceSupplier(() -> { System.out.println("通过supplier构建other2Entity"); return new Other2Entity(); }); } }
@Data @Component public class Other2Entity { private String name; }
可以看出来:other2Entity是通过Supplier创建出来的,如果把MyBeanFactoryPostProcessor 的@Component注释掉,会发生什么呢?咱们试试
从结果得知,这就不是通过Supplier创建的other2Entity,那是怎么创建出来的呢?
当然,这涉及到推断构造方法,spring默认使用无参的构造方法进行实例化。@Component public class Other2Entity { private String name; public Other2Entity(){ System.out.println("通过无参构造方法创建Other2Entity"); } public Other2Entity(String name){ this.name = name; System.out.println("通过有参构造方法创建Other2Entity"); } }
public class Test { public static void main(String[] args) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringAnnotationTest.class); Other2Entity testPrimary = (Other2Entity)context.getBean("other2Entity"); System.out.println(testPrimary); } }
如果不存在无参的构造方法,但是只有一个有参的构造方法,也不会报错@Component @Data public class Other2Entity { private String name; private Other1Entity other1Entity; // public Other2Entity(){ // System.out.println("通过无参构造方法创建Other2Entity"); // } // @Autowired public Other2Entity(Other1Entity other1Entity){ this.other1Entity = other1Entity; System.out.println("通过有参构造方法创建Other2Entity"); } // public Other2Entity(Other1Entity other1Entity, TestPrimary testPrimary){ // this.other1Entity = other1Entity; // System.out.println("通过有参构造方法创建Other2Entity"); // } }
如果有多个有参构造方法,但是没有无参构造方法,会报错。
@Component @Data public class Other2Entity { private String name; private Other1Entity other1Entity; // public Other2Entity(){ // System.out.println("通过无参构造方法创建Other2Entity"); // } // @Autowired public Other2Entity(Other1Entity other1Entity){ this.other1Entity = other1Entity; System.out.println("通过有参构造方法创建Other2Entity"); } public Other2Entity(Other1Entity other1Entity, TestPrimary testPrimary){ this.other1Entity = other1Entity; System.out.println("通过有参构造方法创建Other2Entity"); } }
如果有多个有参构造方法,但是没有无参构造方法,但是在某个有参构造方法上加上@Autowired,则默认使用加了@Autowired进行实例化,不会报错。@Component @Data public class Other2Entity { private String name; private Other1Entity other1Entity; // public Other2Entity(){ // System.out.println("通过无参构造方法创建Other2Entity"); // } @Autowired public Other2Entity(Other1Entity other1Entity){ this.other1Entity = other1Entity; System.out.println("通过有参构造方法创建Other2Entity"); } public Other2Entity(Other1Entity other1Entity, TestPrimary testPrimary){ this.other1Entity = other1Entity; System.out.println("通过有参构造方法创建Other2Entity"); } }
-
BeanDefinition的后置处理
Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),可以对此时的BeanDefinition进行加工,比如:@Component public class MyMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor { @Override public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { if ("other2Entity".equals(beanName)){ beanDefinition.setScope("prototype"); } } }
以上代码就是把other2Entity的beanDefinition的作用范围改为原型的
public class Test { public static void main(String[] args) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringAnnotationTest.class); Other2Entity other2Entity = (Other2Entity)context.getBean("other2Entity", new Other1Entity()); System.out.println(other2Entity); Other2Entity other2Entity1 = (Other2Entity)context.getBean("other2Entity", new Other1Entity()); System.out.println(other2Entity1); } }
虽然Other2Entity在BeanDefinition的后置处理中改为了原型的,但是在实例化的时候,其还是原型的,也就是说在单例池中,也还是会有Other2Entity这个Bean的,证明:
-
实例化后
在处理完BeanDefinition后,Spring又设计了一个扩展点:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(),比如:@Component public class MyPostProcess implements InstantiationAwareBeanPostProcessor { @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if ("other2Entity".equals(beanName)){ System.out.println("实例化前可以做一些操作,比如往redis设值,等等"); } return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { // 实例化后的操作 if ("other2Entity".equals(beanName)){ Other2Entity o = (Other2Entity)bean; o.setName("yzyyzyzyzyzy"); } return false; } }
在实例化后步骤中,我们把Other2Entity 的name属性设置为yzyyzyzyzyzy。测试:
public class Test { public static void main(String[] args) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringAnnotationTest.class); Other2Entity other2Entity = (Other2Entity)context.getBean("other2Entity", new Other1Entity()); System.out.println(other2Entity.getName()); Other2Entity other2Entity1 = (Other2Entity)context.getBean("other2Entity", new Other1Entity()); System.out.println(other2Entity1.getName()); } }
到这里,实例化后操作完成。
spring生命周期步骤简要说明
最新推荐文章于 2024-03-22 11:53:57 发布