在本文中,我们将详细介绍springautowired时发生异常情况的各个方面,并为您提供关于spring对异常的处理的相关解答,同时,我们也将为您带来关于Quartz定时器+Spring+@Auto
在本文中,我们将详细介绍spring autowired时发生异常情况的各个方面,并为您提供关于spring对异常的处理的相关解答,同时,我们也将为您带来关于Quartz定时器+Spring + @Autowired注入 空指针异常、Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效、spring @Autowired map、Spring @Autowired 和 @Resource的有用知识。
本文目录一览:- spring autowired时发生异常情况(spring对异常的处理)
- Quartz定时器+Spring + @Autowired注入 空指针异常
- Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效
- spring @Autowired map
- Spring @Autowired 和 @Resource
spring autowired时发生异常情况(spring对异常的处理)
spring beanFactory那些就不说了,这次发生这个异常纠结好了好久,网上找了很多资料看,终于发现问题。
自动装配bean注入的时候,如果Spring配置定义了aop声明式事务,类似如下方式
<aop:config>
<aop:pointcut id="serviceMethods2"
expression="execution(public * net.villion.framework..*(..))" />
<aop:advisor advice-ref="txAdvice2" pointcut-ref="serviceMethods2" />
</aop:config>
那么@autowire注入bean的时候,会采用代理的模式注入Proxy,如果是接口定义的注入属性对象没有问题,如果是实体bean,那么就会有java.lang.ClassCastException.或者报类似这个 org.springframework.beans.TypeMismatchException: Failed to convert property value of type [com.sun.proxy.$Proxy ? implements .....错误。
以前使用好好的,我也没注意定义aop事务时,把包路径设置得太大了,覆盖了全部,导致注入出现异常情况。
给自己一个教训,这次找了好久,发文希望网上能够给大伙儿一个直接找到问题的地方。
Quartz定时器+Spring + @Autowired注入 空指针异常
在Quartz的定时方法里引用@Autowired注入Bean,会报空指针错误
解决办法:
第一种方法:(推荐,简单,亲测可行)
使用@Resource(name="指定要注入的Bean"),代替@Autowired即可,指定了要注入的Bean名字,就能找到该Bean,就不会空指针了。
@Resource(name = "deviceStateProducerService")
private DeviceStateProducerService deviceStateProducerService;
示例代码:
看下面红色字体部分
代码
@Service("microDeviceStateService")
public class MicroDeviceStateServiceImpl implements MicroDeviceStateService {
@Resource(name = "deviceStateProducerService")
private DeviceStateProducerService deviceStateProducerService;
@Scheduled(cron="0/10 * * * * * ?")
@Lazy(false)
public void pingDeviceState() {
boolean isSuccess = PingUtils.ping("127.0.0.1", 4, 1000);
MicroDeviceState microDeviceState = new MicroDeviceState();
if(!isSuccess) {
logger.debug("连接设备状态失败!");
microDeviceState.setDeviceState("1");
}else {
microDeviceState.setDeviceState("0");
}
microDeviceState.setDeviceFlag("0");
microDeviceState.setIp("127.0.0.1");
DeviceStateBase deviceStateBase = new DeviceStateBase();
BeanUtils.copyProperties(microDeviceState, deviceStateBase);
deviceStateProducerService.deviceStateSender(deviceStateBase);
}
}
有的定时器不生效,在类上加注解@EnableScheduling(spring自带的定时任务功能)
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.2.xsd"
default-lazy-init="true">
<task:scheduler id="scheduler" pool-size="10" />
<task:executor id="executor" keep-alive="3600" pool-size="100-200"
queue-capacity="500" rejection-policy="CALLER_RUNS" />
<task:annotation-driven executor="executor" scheduler="scheduler" />
<!-- 注解配置定时器 -->
<context:annotation-config />
<!-- spring扫描注解的配置(要扫描的包,即定时器所在包) -->
<context:component-scan base-package="com.zit.adapter.camera.CameraListener" />
</beans>
第二种方法:(也可行,不推荐)
使用Spring原生获取Bean的方法 取代 @Autowired注入,同时,不要与定时方法在同一个类
示例代码:
注解方式写了一个定时方法,方法里需要引用Dao层,插入数据库,
直接@Autowired会报空指针异常,做出如下红色字体改动
public class FTPUtil{
// @Autowired
// MicroCameraPassRecordDao microCameraPassRecordDao;
private static MicroCameraPassRecordDao microCameraPassRecordDao = null;
使用Spring获取注入bean
static {
microCameraPassRecordDao =
(MicroCameraPassRecordDao) SpringContextUtils.getApplicationContext().getBean("microCameraPassRecordDao");
}
/**
* 定时从FTP下载图片到本地,在这个方法里调用别的Dao层的方法
*/
@Scheduled(cron="0/20 * * * * * ?")
@Lazy(false)
public synchronized void service() {
FTPUtil ftpUtil = new FTPUtil();
boolean isConnect = ftpUtil.connectServer();
//从FTP下载到工程file下
boolean flag = ftpUtil.download(getFtpPath());
//引用注入Bean,插入数据库
MicroCameraPassRecord cameraRecord = new MicroCameraPassRecord();
cameraRecord.setCameraId(deviceID);
cameraRecord.setAddTime(System.currentTimeMillis());
microCameraPassRecordDao.insert(cameraRecord);
}
}
getBean(引用类名,开头字母小写)
SpringContextUtils
Spring获取Bean的工具类:
package com.zit.util;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Service("springContextUtils")
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
applicationContext = arg0;
}
/**
* 获取applicationContext对象
* @return
*/
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
/**
* 根据bean的id来查找对象
* @param id
* @return
*/
public static Object getBeanById(String id){
return applicationContext.getBean(id);
}
/**
* 根据bean的class来查找对象
* @param c
* @return
*/
public static Object getBeanByClass(Class c){
return applicationContext.getBean(c);
}
/**
* 根据bean的class来查找所有的对象(包括子类)
* @param c
* @return
*/
public static Map getBeansByClass(Class c){
return applicationContext.getBeansOfType(c);
}
}
Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效
今天一 iteye 网页在问答频道提问【Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效】,记录一下。
问题:
@ParentPackage("all")
@Namespace("/project")
public class ProjectAction extends BaseAction {
public final static Logger logger = LoggerFactory
.getLogger(ProjectAction.class);
@Autowired(required=true)
private ProjectService projectService;
如上代码 @Autowired 注入不了
分析:
1、首先从如上代码可以看出 走的是 struts2 注解,而且使用了 struts2 convention 插件,这个插件会扫描如下配置的 actionPackages 寻找 action
<filter>
<filter-name>struts2</filter-name>
<filter-classfilter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>cn.javass</param-value>
</init-param>
2、但此时并没有把 action 交给 spring,
3、接下来,因为集成了 spring(有 struts2-spring-plugin),所以要使用 StrutsSpringObjectFactory 创建 bean,代码分析
@Override
public Object buildBean(String beanName, Map<String, Object> extraContext, boolean injectInternal) throws Exception {
Object o;
if (appContext.containsBean(beanName)) {
o = appContext.getBean(beanName); //拿不到bean
} else {
Class beanClazz = getClassInstance(beanName);
o = buildBean(beanClazz, extraContext); //所以创建了一个
}
if (injectInternal) {
injectInternalBeans(o);
}
return o;
}
/**
* @param clazz
* @param extraContext
* @throws Exception
*/
@Override
public Object buildBean(Class clazz, Map<String, Object> extraContext) throws Exception {
Object bean;
try {
// Decide to follow autowire strategy or use the legacy approach which mixes injection strategies
if (alwaysRespectAutowireStrategy) {//默认false
// Leave the creation up to Spring
bean = autoWiringFactory.createBean(clazz, autowireStrategy, false);
injectApplicationContext(bean);
return injectInternalBeans(bean);
} else {
bean = autoWiringFactory.autowire(clazz, AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR, false); //只走构造器注入
bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName());
// We don''t need to call the init-method since one won''t be registered.
bean = autoWiringFactory.applyBeanPostProcessorsAfterInitialization(bean, bean.getClass().getName());
return autoWireBean(bean, autoWiringFactory);
}
} catch (UnsatisfiedDependencyException e) {
if (LOG.isErrorEnabled())
LOG.error("Error building bean", e);
// Fall back
return autoWireBean(super.buildBean(clazz, extraContext), autoWiringFactory);
}
}
我们在 shiro 里使用如下代码 去代理 shiro 的代理:
<bean id="proxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor">
<property name="proxyTargetClass" value="true"/>
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean>
//StrutsSpringObjectFactory 的如下代码将执行处理器的预处理
bean = autoWiringFactory.applyBeanPostProcessorsBeforeInitialization(bean, bean.getClass().getName());
//DefaultAdvisorAutoProxyCreator 的 postProcessBeforeInstantiation:将去完成代理 bean 因此此时将返回代理 Bean
// 接着 StrutsSpringObjectFactory 的 autoWireBean (bean, autoWiringFactory); 进行注入 所以此时注入到的是代理对象,因此如果字段注入 将注入不了。
解决方案
1、不使用 actionPackages 而是 在类上加 @Controller @Scope 完全走 spring
2、使用 setter 注入 而不是字段 如
private ProjectService projectService;
@Autowired(required=true)
public void setProjectService() {
}
spring @Autowired map
注入map,平常一般不会这么做,今天在写一个demo时,有如下一段注入代码:
map bean 的创建
@Bean(name="userMap")
public Map<Long, User> userMap() {
return new ConcurrentHashMap<Long, User>();
}
// 注入
@Autowired
@Qualifier("userMap")
private Map<Long, User> userMap;
怕出错,我还特意加了Qualifier限定符,但是spring 容器就起不来了,异常如下,大概意思就是map的key要是String类型才行:
Caused by: org.springframework.beans.FatalBeanException: Key type [class java.lang.Long] of map [java.util.Map] must be assignable to [java.lang.String]
原因如下:org.springframework.beans.factory.support.DefaultListableBeanFactory中的一段代码
Class<?> keyType = descriptor.getMapKeyType();
if (keyType == null || !String.class.isAssignableFrom(keyType)) {
if (descriptor.isRequired()) {
throw new FatalBeanException("Key type [" + keyType + "] of map [" + type.getName() +
"] must be assignable to [java.lang.String]");
}
return null;
}
用set 方法也不行。但是使用如下方法却奏效了:
@Resource(name = "userMap")
private Map<Long, User> userMap;
Spring @Autowired 和 @Resource
@Autowired
@Autowired 注释首先根据 Bean 名称匹配,如果找不到再根据类型匹配
@Resource
默认使用类型匹配,但是可以指定名称 @Resource(name = "BeanName")
示例
@ComponentScan
@Configuration
public class AutowiredDemo {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AutowiredDemo.class);
Action action = applicationContext.getBean(Action.class);
action.handle();
}
}
@Component
class LocalService implements Service {
@Override
public void process() {
System.out.println("local process");
}
}
@Component
class RemoteService implements Service {
@Override
public void process() {
System.out.println("remote process");
}
}
@Component
class Action {
// 正确的,根据 LocalService 的类型可以唯一匹配到一个 Bean
@Autowired
private LocalService localService1;
// 错误的,根据 localService1 这个名称无法匹配到一个 Bean
// 根据 Service 的类型匹配到了两个 Bean,不唯一,所以也是错误的
@Autowired
private Service localService1;
// 正确的,根据 localService 的名称可以匹配到唯一的 Bean
@Autowired
private Service localService;
// 正确的,Resource 在不指定名称的时候使用类型匹配
@Resource
private LocalService abc;
// 正确的,Resource 可以指定名称
@Resource(name = "localService")
private Service localService1;
public void handle() {
localService1.process();
}
}
关于spring autowired时发生异常情况和spring对异常的处理的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Quartz定时器+Spring + @Autowired注入 空指针异常、Shiro+Struts2+Spring3 加上 @RequiresPermissions 后 @Autowired 失效、spring @Autowired map、Spring @Autowired 和 @Resource的相关知识,请在本站寻找。
本文标签: