开发者社区> 问答> 正文

Spring的注解和注入问题?报错

spring提供的三种注入方式:设置注入、构造注入、注解注入

先上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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
       		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-2.5.xsd
            http://www.springframework.org/schema/tx 
            http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
	        http://www.springframework.org/schema/aop 
	        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
	        
	<!-- 打开aop自动扫描管理器 -->
	<aop:aspectj-autoproxy/>
	<!-- 打开组件自动扫描管理器 --><!-- 扫描cn.zzbj下的组件 -->
    <context:component-scan base-package="cn.zzbj"/>
	<context:property-placeholder location="classpath:jdbc.properties"/>
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${driverClassName}"/>
		<property name="url" value="${url}"/>
		<property name="username" value="${username}"/>
		<property name="password" value="${password}"/>
		
		<!-- 连接池启动时的初始值 -->
		<property name="initialSize" value="${initialSize}"/>
		<!-- 连接池的最大值 -->
		<property name="maxActive" value="${maxActive}"/>
		<!-- 最大空闲值,当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
		<property name="maxIdle" value="${maxIdle}"/>
		<!-- 最小空闲值,当空闲的连接数少于阀值时,连接池就会预申请一些连接,以免高峰期来不及申请 -->
		<property name="minIdle" value="${minIdle}"/>
	</bean>
	<!-- 声明定义事务管理器 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	<!-- 打开事物管理器注解标签 -->
	<tx:annotation-driven transaction-manager="txManager"/>
</beans>



业务bean:
package cn.zzbj.service.impl;

import java.util.List;

import javax.annotation.Resource;
import javax.sql.DataSource;

import org.springframework.context.annotation.Scope;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.zzbj.entity.Person;
import cn.zzbj.service.PersonService;

@Service("personService") @Scope("prototype") @Transactional
public class PersonServiceBean implements PersonService {
	private DataSource dataSource;
	private JdbcTemplate jdbcTemplate;
	
	public void setDataSource(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public void save(Person person) {
		System.out.println(jdbcTemplate==null);
		jdbcTemplate.update("insert into person(name) values(?)", new Object[]{person.getName()},
				new int[]{java.sql.Types.VARCHAR});
		//throw new RuntimeException();
	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public void update(Person person) {
		//测试datasource
		System.out.println(dataSource);
	}

	@Transactional(rollbackFor=Exception.class)
	@Override
	public void delete(Integer id) {
		// TODO Auto-generated method stub

	}

	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	@Override
	public Person getPerson(Integer id) {
		// TODO Auto-generated method stub
		return null;
	}

	@Transactional(propagation=Propagation.NOT_SUPPORTED)
	@Override
	public List<Person> getPersons() {
		// TODO Auto-generated method stub
		return null;
	}

}



测试方法:
@Test
	public void test() {
		ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
		PersonService ps = (PersonService) ac.getBean("personService");
		try {
			ps.update(new Person("aa"));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}



问:配置文件中已经有了dataSource的bean了,这里采用了setter注入方式,但是没有dataSource的值是null,如果给属性dataSource添加上@Resource注解结果就不为null,setter方法中加上this.dataSource=dataSource;结果还是一样为null。


而使用上述粘贴的代码测试save()方法的时候报错:

java.lang.NullPointerException

	at cn.zzbj.service.impl.PersonServiceBean.save(PersonServiceBean.java:31)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:307)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at com.sun.proxy.$Proxy11.save(Unknown Source)
	at cn.zzbj.test.ServiceTest.test(ServiceTest.java:24)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)



展开
收起
爱吃鱼的程序员 2020-06-14 18:23:40 455 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB

    1.最初的配置是service的属性dataSource不加@Resource注解,结果dataSource为空容易理解,这就是一个普通属性,你么有初始化值
    2.你在dataSource属性上加注解<aclass='referer'target='_blank'>@Resource,那么就是初始话了dataSource,这时dataSource不为空,但是dataSource有值不是调用setDataSource方法的(你可以看你的方法setDataSource你是没有设置dataSource的传入值)
    3.<aclass='referer'target='_blank'>@Resource注解是写在属性上,不是方法上的,所以写在方法上是没效的,所以dataSource为空
    4.第二种方法的dataSource虽然不为空,但是这个service没有构造JdbcTemplate,因为@Resource注解没有调用setDataSource()方法




    解决办法:
    在xml配置该service的bean,这样配置才会调用setDataSource()方法初始化JdbcTemplate,(这时service的dataSource为空,因为你没有this.dataSource=dataSource)
    初始化了JdbcTemplate,你调用save才不会报空异常


    如果你是想使用注解方法,请将JdbcTemplate也当成是一个全局bean,使用@Resource调用,如果不是,每个service你都需要构造或者加一个BaseSservice,所有service都继承
    classclassBaseSservice{
    @Resource
    privateDataSourcedataSource;


    privateJdbcTemplatejdbcTemplate;


    @ModelAttribute
    protectedvoidinitService(){
    jdbcTemplate=newJdbcTemplate(this.dataSource);
    }
    }
    <preclass="brush:java;toolbar:true;auto-links:false;">@Service("personService")@Scope("prototype")@TransactionalpublicclassPersonServiceBeanimplementsPersonService{privateDataSourcedataSource;privateJdbcTemplatejdbcTemplate;publicvoidsetDataSource(DataSourcedataSource){this.jdbcTemplate=newJdbcTemplate(dataSource);}

    这里只是说PersonServiceBean是一个需要spring管理的bean,bean的id为persionService。

    bean为prototype方式管理。

    bean有事物。

    你也没有配置让spring给你注入datasoure啊。在datasource上添加注解,spring才会知道你需要注入这个属性。






    恩,的确是这样,需要给加上注释回复<aclass='referer'target='_blank'>@影非弦:下面的评论已经说得很详细了。spring不是通过有没有setter和getter方法来判断注入的。需要加额外的注解,spring才能知道。没有setter和getter方法,配置正确的情况下,spring也可以注入。这里有dataSource的setter方法啊,使用setter注入的。

    <atarget="_blank"rel="nofollow">SpringInjectionwith<aclass='referer'target='_blank'>@Resource,@Autowiredand@Inject

    看看这个就明白了


    http://www.zhanghenglei.com/spring-injection-with-resource-autowired-and-inject/

    <spanstyle="font-family:微软雅黑,Verdana,sans-serif,宋体;font-size:14px;line-height:22px;background-color:#FFFFFF;">配置文件中已经有了dataSource的bean了,这里采用了setter注入方式。。。。

    <spanstyle="font-size:14px;line-height:22px;background-color:#FFFFFF;">如果用setter方式的话,<spanstyle="font-family:Consolas,'BitstreamVeraSansMono','CourierNew',Courier,monospace;font-size:14px;line-height:15.3999996185303px;background-color:#FFFFFF;">PersonServiceBean应该也配置在xml中,并且property其中一个为dataSource

    <spanstyle="font-size:14px;line-height:22px;background-color:#FFFFFF;">要么全部用注解,要么全部用xml配置。不然出一堆问题搞死自己啊。

    你set注入的方式你还没搞懂,不是有set方法 然后就可以自动注入。其他人我没看,巴顿说的没错。<atarget='_blank'>@影非弦慢慢来恩,有点混乱了

    2020-06-14 18:23:58
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧 立即下载
微服务架构模式与原理Spring Cloud开发实战 立即下载
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载

相关实验场景

更多