基于注解的IoC容器配置
有了前面基于xml的IoC容器配置,使用注解的方式来配置Ioc容器,会发现这是个简单容易的过程。简化了很多工作量,减少了很多的注入配置。
首先修改xml中配置,移除IUserService和IUserDao的配置,修改xml的架构,使用Context Schema Configuration架构
<?xml version="1.0" encoding="UTF-8"?>
<!--这里使用context schema configuration-->
<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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 通知spring要扫描的包 -->
<context:component-scan base-package="com"></context:component-scan>
<!--配置QueryRunner-->
<bean id="query" class="org.apache.commons.dbutils.QueryRunner" scope="prototype" > <!--线程安全:多个dao同时操作数据库,一个runner对象会存在线程安全问题,这里采用多利模式-->
<!--配置数据源-->
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--数据库连接信息-->
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://192.168.1.8:3306/studenms?serverTimezone=UTC"></property>
<property name="user" value="root"></property>
<property name="password" value="sa"></property>
</bean>
</beans>
使用注解@Service,@Repository,@Autowired
@Service(value = "IUserService")
public class UserserviceImpl implements IUserService {
@Autowired
private IUserDao userDao;
// your code...
}
@Repository(value = "UserDao")
public class UseDaoImpl implements IUserDao {
@Autowired
private QueryRunner query;
// your code...
}
测试代码:
public class AnnotationIoCTest {
ApplicationContext context = null;
IUserService userService = null;
@Before
public void getApplicationContext() {
context = new ClassPathXmlApplicationContext("bean.xml");
userService = context.getBean("IUserService", IUserService.class);
}
@Test
public void finAllTest() throws SQLException {
List<UserEntity> entityList = userService.findAll();
for (UserEntity userEntity : entityList) {
System.out.println(userEntity);
}
}
}
注意事项
-
使用注解时,一定要在xml中使用context:component-scan,它的作用是指定spring IoC容器创建时要扫描注解的包
<context:component-scan base-package="com"></context:component-scan>
否则会抛出无法找到名叫”IUservice”的Bean:
-
一定要在xml配置org.apache.commons.dbutils.QueryRunner 这里可能会产生一个疑问,使用了注解@Autowried来注入QueryRunner,为什么还要在xml中配置呢?因为在QueryRunner中注入了c3p0的DataSource(数据库连接信息),如果不配置,就会无法使用c3p0,也不能连接数据库。如果仅仅在xml中配置了QueryRunner的注入,而不是用@Autowired注解,会怎么样呢?
把QueryRunner的注解去掉
//@Autowired
private QueryRunner query;
执行测试,结果如下:
空指针异常,没有获取到query对象,说明没有注入成功。所以这里一定要注意。
到了这里会产生僧一个疑问,不是使用注解吗,怎么还是有xml配置?接下来开始移除xml中的配置
移除xml
-
新建一个配置类
/**
* 配置类
*/
@Configuration
@ComponentScan(value = {"com"})
public class SpringConfiguration {
}
@Configuration:标记配置类 @ComponentScan(value = {“com”}):扫描注解包,相当于xml中的
<constructor-arg name="ds" ref="dataSource"></constructor-arg>
-
创建QueryRunner对象并存入IoC容器
@Bean(name = "queryRunner")
@Scope(value = "prototype")
public QueryRunner instancceQueryRunner(DataSource dataSource){
return new QueryRunner(dataSource);
}
@Bean:作用是将当前方法的返回值作为一个Bean对象,存入IoC容器中。在IoC容器中Bean对象都是以Key-Value形式存储的,那么当@Bean不赋予属性时,它是的name(vaue)属性默认是当前方法名
@Scope(value = “prototype”):作用是创建多例,保证线程安全,如果这里不写@Scope注解或者不写属性或者Scope(value = “singleton”),那么创建的Bean对象默认是单例,存在着线程安全问题。
-
配置数据源
@Bean(name = "dataSource")
public DataSource instanceDataSource() throws PropertyVetoException {
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
comboPooledDataSource.setJdbcUrl("jdbc:mysql://192.168.1.8:3306/studenms?serverTimezone=UTC");
comboPooledDataSource.setUser("root");
comboPooledDataSource.setPassword("sa");
return comboPooledDataSource;
}
这里存在一个问题 创建QueryRunner对象的方法的参数报错,这是为什么?写一个方法为什么会参数报错。这是因为使用了@Bean注解,spring会在IoC容器中找dataSource的Bean对象,他没有找到DataSource的Bean对象,所以才会报错。它的寻找原理和@AutoWried的机制一样,后面介绍。
将instanceDataSource的注解放开,发现错误消失
神奇的框架!
-
删除bean.xml文件,修改测试代码
这里和使用xml注入的测试只有一处最重要的区别,其它都一样,就是这一行:
context = new AnnotationConfigApplicationContext(SpringConfiguration.class);
区别在于AnnotationConfigApplicationContext与ClassPathXmlApplicationContext,从名称可以看出,这个类是用来读取注解配置的。
原文始发于微信公众号(程序员玄之):基于注解的Spring-IoC容器配置
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/43045.html