欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

springboot 实现bean手动注入操作

程序员文章站 2022-03-20 22:54:22
1、springboot启动类实现接口applicationlistener,实现方法onapplicationevent,初始化上下文pac...

1、springboot启动类实现接口applicationlistener<contextrefreshedevent>,实现方法onapplicationevent,初始化上下文

package test.projecttest;
import org.mybatis.spring.boot.autoconfigure.mybatisautoconfiguration;
import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.enableautoconfiguration;
import org.springframework.boot.autoconfigure.springbootapplication;
import org.springframework.boot.autoconfigure.jdbc.datasourceautoconfiguration;
import org.springframework.boot.autoconfigure.jdbc.datasourcetransactionmanagerautoconfiguration;
import org.springframework.boot.system.applicationpidfilewriter;
import org.springframework.context.applicationlistener;
import org.springframework.context.event.contextrefreshedevent;
import test.projecttest.util.springcontextutil;
@enableautoconfiguration(exclude = {datasourceautoconfiguration.class,datasourcetransactionmanagerautoconfiguration.class, mybatisautoconfiguration.class})
@springbootapplication(scanbasepackages={"test.projecttest"})
public class testapplication implements applicationlistener<contextrefreshedevent>
{
 public static void main( string[] args )
 {
  springapplication application = new springapplication(testapplication.class);
  application.addlisteners(new applicationpidfilewriter());
  application.run(args);
  system.out.println( "启动成功" );
 }
 @override
 public void onapplicationevent(contextrefreshedevent event) {
  springcontextutil.setapplicationcontext(event.getapplicationcontext());  
 }
}

2.springcontextutil工具类初始化applicationcontext applicationcontext

package test.projecttest.util;
import org.springframework.context.applicationcontext;
/**
 * 获取spring容器,以访问容器中定义的其他bean
 */
public class springcontextutil{
 //spring上下文
 private static applicationcontext applicationcontext;
 
 /**
  * 实现applicationcontextaware接口的回调方法,设置上下文环境
  * @param applicationcontext
  */
 public static void setapplicationcontext(applicationcontext applicationcontext){
  if(null==springcontextutil.applicationcontext)
   springcontextutil.applicationcontext=applicationcontext;
 }
 
 public static applicationcontext getapplicationcontext(){
  return applicationcontext;
 }
  /**
  * 通过name获取 bean.
  *
  * @param name
  * @return
  */
 public static object getbean(string name) {
  return getapplicationcontext().getbean(name);
 }
 /**
  * 通过name获取 bean.
  *
  * @param clazz
  * @return
  */
 public static <t> t getbean(class<t> clazz) {
  return getapplicationcontext().getbean(clazz);
 }
 /**
  * 通过name,以及clazz返回指定的bean
  *
  * @param name
  * @param clazz
  * @return
  */
 public static <t> t getbean(string name, class<t> clazz) {
  return getapplicationcontext().getbean(name, clazz);
 }
}

3.获取bean

package test.projecttest.util;
import test.projecttest.mapper.slave.dailydatamapper;
public class testutil{ 
 private static dailydatamapper dailydatamapper; 
 static{//手动注入bean
  if(dailydatamapper==null){
   dailydatamapper = (dailydatamapper)springcontextutil.getbean("dailydatamapper");
  }
 }
 public static void test(){
  dailydatamapper.selectbyprimarykey(1);
 } 
}

补充:springboot中bean的实例化和属性注入过程

springboot版本(2.0.4 release)

大致描述springboot中bean的实例化和属性注入过程流程

1) 在某一时刻spring调用了bean工厂的getbean(beanname)方法。beanname可能是simplecontroller,或者simpleservice,simpledao,顺序没关系(因为后面会有依赖关系的处理)。我们假设simplecontroller吧

2)getbean方法首先会调用bean工厂中定义的getsingleton(beanname)方法,来判断是否存在该名字的bean单例,如果存在则返回,方法调用结束(spring默认是单例,这样可以提高效率)

3) 否则,spring会检查是否存在父工厂,如果有则返回,方法调用结束

4) 否则,spring会检查bean定义(beandefinition实例,用来描述bean结果,component-scan扫描后,就是将beandefinition实例放入bean工厂,此时还没有被实例化)是否有依赖关系,如果有,执行1)步,获取依赖的bean实例

5) 否则,spring会尝试创建这个bean实例,创建实例前,spring会检查调用的构造器,并实例化该bean,(通过constructor.newinstance(args)进行实例化)

6) 实例化完成后,spring会调用bean工厂的populatebean方法来填充bean实例的属性,也就是自动装配。populatebean方法便是调用了beanpostprocessor实例来完成属性元素的自动装配工作

7)在元素装配过程中,spring会检查被装配的属性是否存在自动装配的其他属性,然后递归调用getbean方法,知道所有@autowired的元素都被装配完成。如在装配simplecontroller中的simpleservice属性时,发现simpleserviceimpl实例中存在@autowired属性simpledao,然后调用getbean(simpledao)方法,同样会执行1)----7)整个过程。所有可以看成一个递归过程。

8)装配完成后,bean工厂会将所有的bean实例都添加到工厂中来。

bean的实例化

1. 进入springapplication类中refreshcontext()方法

springboot 实现bean手动注入操作

2. 进入abstractapplicationcontext类中refresh()方法,找到this.finishbeanfactoryinitialization()方法,这个方法就是完成beanfactory的实例化

springboot 实现bean手动注入操作

3. 进入abstractapplicationcontext类中finishbeanfactoryinitialization()方法,找到preinstantiatesingletons()

springboot 实现bean手动注入操作

4. 进入defaultlistablebeanfactory类中preinstantiatesingletons()方法,找到getbean()方法

springboot 实现bean手动注入操作

5. 进入abstractbeanfactory类中getbean()方法,找到dogetbean()方法

springboot 实现bean手动注入操作

6. 在abstractbeanfactory类中dogetbean方法中,找到createbean()方法

springboot 实现bean手动注入操作

7. 进入abstractautowirecapablebeanfactory类中createbean方法中,找到docreatebean()方法

springboot 实现bean手动注入操作

8. 在abstractautowirecapablebeanfactory类中docreatebean()方法中,找到createbeaninstance()方法,看名字就知道是实例化bean的

springboot 实现bean手动注入操作

9. 在abstractautowirecapablebeanfactory类createbeaninstance()方法中,找到instantiatebean()方法

springboot 实现bean手动注入操作

10. 在abstractautowirecapablebeanfactory类instantiatebean()方法中,找到instantiate()方法

springboot 实现bean手动注入操作

11. 在simpleinstantiationstrategy类instantiate()方法中,找到instantiateclass()方法

springboot 实现bean手动注入操作

12. 在beanutils类instantiateclass()方法中,可知bean的实例化是通过constructor.newinstance()进行实例化

springboot 实现bean手动注入操作

bean的属性注入

1. 在abstractautowirecapablebeanfactory类docreatebean()方法中,找到populatebean()方法,从名字可知是用来填充bean的

springboot 实现bean手动注入操作

2. 在abstractautowirecapablebeanfactory类中populatebean()方法,找到postprocesspropertyvalues()方法

springboot 实现bean手动注入操作

3. 进入autowiredannotationbeanpostprocessor类中postprocesspropertyvalues()方法中,找到findautowiringmetadata()方法,在这个方法中,如果属性中含有@autowired注解则会递归getbean()。没有然后进入inject()方法中

springboot 实现bean手动注入操作

4. 进入autowiredannotationbeanpostprocessor类inject方法中,找到resolvedependency()方法,通过这个方法获取对应字段的值

springboot 实现bean手动注入操作

5. 进入autowiredannotationbeanpostprocessor类inject方法中,找到field.set(bean, value)方法,通过反射将值设置到属性中

springboot 实现bean手动注入操作

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。