springboot 实现bean手动注入操作
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()方法
2. 进入abstractapplicationcontext类中refresh()方法,找到this.finishbeanfactoryinitialization()方法,这个方法就是完成beanfactory的实例化
3. 进入abstractapplicationcontext类中finishbeanfactoryinitialization()方法,找到preinstantiatesingletons()
4. 进入defaultlistablebeanfactory类中preinstantiatesingletons()方法,找到getbean()方法
5. 进入abstractbeanfactory类中getbean()方法,找到dogetbean()方法
6. 在abstractbeanfactory类中dogetbean方法中,找到createbean()方法
7. 进入abstractautowirecapablebeanfactory类中createbean方法中,找到docreatebean()方法
8. 在abstractautowirecapablebeanfactory类中docreatebean()方法中,找到createbeaninstance()方法,看名字就知道是实例化bean的
9. 在abstractautowirecapablebeanfactory类createbeaninstance()方法中,找到instantiatebean()方法
10. 在abstractautowirecapablebeanfactory类instantiatebean()方法中,找到instantiate()方法
11. 在simpleinstantiationstrategy类instantiate()方法中,找到instantiateclass()方法
12. 在beanutils类instantiateclass()方法中,可知bean的实例化是通过constructor.newinstance()进行实例化
bean的属性注入
1. 在abstractautowirecapablebeanfactory类docreatebean()方法中,找到populatebean()方法,从名字可知是用来填充bean的
2. 在abstractautowirecapablebeanfactory类中populatebean()方法,找到postprocesspropertyvalues()方法
3. 进入autowiredannotationbeanpostprocessor类中postprocesspropertyvalues()方法中,找到findautowiringmetadata()方法,在这个方法中,如果属性中含有@autowired注解则会递归getbean()。没有然后进入inject()方法中
4. 进入autowiredannotationbeanpostprocessor类inject方法中,找到resolvedependency()方法,通过这个方法获取对应字段的值
5. 进入autowiredannotationbeanpostprocessor类inject方法中,找到field.set(bean, value)方法,通过反射将值设置到属性中
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。
下一篇: 系统性能提升优先法宝 | 缓存应用实践
推荐阅读
-
PyQt5内嵌浏览器注入JavaScript脚本实现自动化操作的代码实例
-
SpringBoot实现ORM操作MySQL的几种方法
-
SpringBoot实现ORM操作MySQL的几种方法
-
【原】无脑操作:IDEA + maven + Shiro + SpringBoot + JPA + Thymeleaf实现基础认证权限
-
SpringBoot无法注入JpaRepository接口 (找不到指定Bean)
-
SpringBoot开发案例之拦截器注入Bean
-
SpringBoot操作mongo实现方法解析
-
springboot实现热部署操作方法
-
SpringBoot整合Elasticsearch并实现CRUD操作
-
详解SpringBoot 多线程处理任务 无法@Autowired注入bean问题解决