手动向Spring容器中注入对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手动向Spring容器中注入对象相关的知识,希望对你有一定的参考价值。

参考技术A 手动向Spring容器中注入对象的方法有很多,本文将简单阐述其中的四种

我们可以实现一个BeanFactory的后置处理器,在其中就可以获得BeanFactory,这样就可以调用registerSingleton方法。
注:此处bean的名字可以自定义,如这里就定义为sherlock。

如果在容器中获取该类

控制台输出:

对象就已成功注入到Spring容器中了。
注:其实在context中也有registerBean方法,可以实现一样的效果。(ApplicationContext其实继承了BeanFactory,所以它也拥有Bean工厂的功能,除此之外ApplicationContext还继承了很多其他的类,拥有一些辅助功能。总的来说,ApplicationContext其实包括了BeanFactory)

在配置类中,使用@Bean注解,返回一个想要注入的对象。@Bean括号中是bean的名字,默认为类名的小写形式。

控制台输出:

既然提到了Factory‘Bean,就不得不提到BeanFactory。关于这两个的区别,可以看下我的另一篇文章。 https://www.jianshu.com/p/91d21128d2a9
我们可以创建一个类去实现FactoryBean接口

控制台输出:

@Import只能用在类上 ,@Import通过快速导入的方式实现把实例加入spring的IOC容器中
@Import的三种用法主要包括:

注意:这样注入的类名为类的全限定名。

@Import三种方式的总结
第一种用法:@Import( 要导入的容器中的组件 ):容器会自动注册这个组件,id默认是全类名
第二种用法:ImportSelector:返回需要导入的组件的全类名数组,springboot底层用的特别多。
第三种用法:ImportBeanDefinitionRegistrar:手动注册bean到容器

好了,以上就是四种手动向Spring容器中注入对象的方法。总结一下吧,分别是:

JAVA WEB 过滤器(Filter)中向容器 Spring 注入 bean

  如果直接使用 @Autoware 获取 bean 会直接使该 bean 为 null,这是因为这种配置过滤器的方法无法在过滤器中使用 Spring bean,因为 Filter 比 bean 先加载,也就是 Spring 会先加载 Filter 指定的类到 Container 中,这样 Filter 中注入的 Spring bean 就为 null 了。

解决方法:  

  1. 直接在 init() 初始化方法中手动配置 bean。

  (1)开始的声明

1 MenuService menuService = null;
2 ApplicationContext applicationContext = null;

  (2)初始化方法

1 @Override
2     public void init(FilterConfig filterConfig) throws ServletException {
3         // 手动配置 bean
4         ServletContext servletContext = filterConfig.getServletContext();
5         applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
6         menuService = (MenuService) applicationContext.getBean("menuService");
7     }

  (3)doFilter() 方法的使用

1 menuService.getOwnMenuByUserId(userId.toString(), loginType.toString());

  2. 代理 —— DelegatingFilterProxy 类。

配置过滤器:

1 <filter>  
2     <filter-name>permission</filter-name>  
3     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
4 </filter>  

在 Spring 的配置文件中配置:

1 <bean id="permission" class="com.my.myfilter">  

DelegatingFilterProxy 类遵循 filter-name-bean 的原则,会根据 web.xml 中 filter-name 的值查找到 spring 配置文件中 id 与 filter-name 相同的值,然后把接受到的处理信息传递给相对应的类处理。如果想自定义 filter 处理的 bean,可以在 filter 配置中添加下面一段:

1 <init-param>  
2     <param-name>targetBeanName</param-name>  
3     <param-value>Spring-bean-name</param-value>  
4 </init-param> 

这句话会指定该 filter 使用 Spring-bean-name 去处理该请求。这时候你会发现 Filter.init() 和 Filter.destory() 无法使用 spring bean,这是因为默认 filter 的生命周期是有 tomcat 这类服务器管理的,在配置:

1 <init-param>  
2     <param-name>targetFilterLifecycle</param-name>  
3     <param-value>true</param-value>  
4 </init-param>  

 

这时候就是由 spring 管理 filter 的生命周期,这样就可以在 init() 和 destory() 使用 spring bean 了。

还有一个重要的事情,有时候你会发现在请求 filter 处理的 url 的时候程序会报错 —— No WebApplicationContext found: no ContextLoaderListener registered?

出现这个的原因是因为:filter 会优于 servlet 先加载到容器里面,如果我们只是在 org.springframework.web.servlet.DispatcherServlet 中配置了 contextConfigLocation,指定了 spring 配置文件位置的话,程序会无法访问 spring bean,解决方法很简单,在 web.xml 配置上:

1 <context-param>  
2     <param-name>contextConfigLocation</param-name>  
3     <param-value>classpath:/conf/web-context.xml</param-value>  
4 </context-param>  
5 <listener>   
6         <listener-class>   
7             org.springframework.web.context.ContextLoaderListener   
8         </listener-class>   
9     </listener>  

这样让 spring bean 第一时间加载到容器里面,这样就不会有 No WebApplicationContext found: no ContextLoaderListener registered? 这个错误了。

 

以上第一个方法亲测完全可以实现,第二种方法暂未测试,第二种方法来源地址:

 http://blog.csdn.net/godha/article/details/13025099

以上是关于手动向Spring容器中注入对象的主要内容,如果未能解决你的问题,请参考以下文章

如何把对象手动注入Spring容器并实现依赖注入

JAVA WEB 过滤器(Filter)中向容器 Spring 注入 bean

手动注入bean时 , 根据条件注入bean

Spring第二篇:Spring容器的基本使用及原理

spring ioc容器之Bean实例化和依赖注入

spring自动注入的三种方式