2019-8-7 [Java_Spring]6.使用注解简化Spring的IOC与DI的配置 按类型注入属性值 给属性按类型赋值 具体实现示例

20 篇文章 0 订阅

6.使用注解简化Spring的IOC配置

6.1 为什么需要注解配置?

因为我们已经完后了 spring IOC和DI 也进行了Spring 一张表的CURD操作,但是我们发现了一个问题

<!-- 创建一个DAO层对象 -->
<bean id="userDAO" class="com.hnxy.dao.impl.UserDAOImpl">
	<property name="qr" ref="qr" />
</bean>
<!-- 创建一个Service对象 -->
<bean id="userService" class="com.hnxy.service.impl.UserServiceImpl">
	<property name="userDAO" ref="userDAO" />
</bean>

上面这段代码,看似好像没有什么问题,但是大家可以仔细的想一想,如果你的DAO对象和Service对象有很多个需要配置的话,那么Bean的数量将会是惊人的一个数量

那么此时就有一个问题 : Bean的数量增多 XML配置的难度也随之增加 维护起来也不好维护

遇到这样问题我们改如何解决 ?
解决XML问题的通用玩法 如果你觉得你的XML配置很难 那么一定 要先考虑使用注解优化一个配置!

注解 :
标记语言 可以把一个类 一个方法标记为一个功能
注解 和 XML的本质其实是一样

6.2 IOC与DI的注解优化配置

删除spring配置文件中的原有对象bean的配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

	<!-- 需要一个数据源对象 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/userdb?characterEncoding=UTF-8" />
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>
	<!-- 创建SQL的执行对象 -->
	<bean id="qr" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
		<!-- 构造函数创建对象 -->
		<constructor-arg name="ds" ref="dataSource" />
	</bean>	
</beans>

注意只保留 DataSource 和 QueryRunner 我们自己定义的类的bean我们用注解配置
我们删除了两个bean 一个是 UserDAOImpl 一个是UserServiceImpl

6.3 IOC与DI的注解配置

注解存在的意义 : XML的另外一种配置方案而已,它能够减少我们在XML中配置的bean标签的数量,从而简化XML配置

主要用途 : 配置bean

  1. @Component = <bean id="" class="" />
  2. @Component("userDAO") = <bean id="userDAO" class="com.hnxy.dao.impl.UserDAOImpl" />
@Component
public class UserDAOImpl implements UserDAO {

这句话就相当于

<bean id="UserDAOImpl" class="com.hnxy.dao.impl.UserDAOImpl" />

最起码注解的好处就是 你不用再指定类型

但是 此处需要注意的是,你的bean虽然创建完了 但是它被创建在类中了 spring配置文件并不知道你有这个bean

所以我们必须让spring知道我们现在有一个bean在UserDAOImpl
那么我们怎么让spring配置文件知道我有这么一个bean

其实 spring给你提供了一个 注解bean的包扫描器的功能可以通过配置包扫描器 扫描某个包下的所有注解bean

那么此处我们怎么配置注解bean的包扫描器呢?

  1. 引入相关的功能 这个包扫描器的功能 在spring-context这个包下,所以我们要引入
    这个context功能
    声明引入功能标签
xmlns:context="http://www.springframework.org/schema/context"

添加这个标签的XSD文件

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
  1. 引入完成后我们直接配置包的扫描器即可
<!-- 节省时间 -->
<context:component-scan base-package="com.hnxy.dao" />
<context:component-scan base-package="com.hnxy.service" />

改造完成后经过测试可以知道 我们用注解创建的bean是单例模式,那么怎么把单例的bean变成多例的bean
如果你想把一个bean变成多例 只需要加入一个 @scope注解即可

@Component("userService")
@Scope("prototype")
public class UserServiceImpl implements UserService {
    ......代码略
}

那么到此我们已经可以用注解创建bean,但是bean里面的属性我们无法赋值那怎么办呢?

6.4 注解

6.4.1 @Autowired

按类型注入属性值 给属性按类型赋值

6.4.2 @Qualifier(“UserService”)

可以按照bean的id进行配置 给属性按名称赋值

@Autowired 注解可以按类型注入相关的属性值,但是有一个问题,按类型注入一个类型只能出现一个bean
假如说你按类型注入的时候报错了,那么你其实还可以按照BeanID的形式指定需要注入的bean

@Autowired
@Qualifier("qr1")
private QueryRunner qr;

@Component 可以把一个类变成bean,当然这个注解的语义不够明显,

6.4.3 @Component又被分成三个注解

@Repository 可以把一个DAO层变成一个bean
@Service 可以把一个service的变成bean
@controller 可以把一个controller变成一个bean

6.4.4 区别 :

@Service @Controller @Repository 只是语义更加明确了,功能都是一样的其实底层就是Component
给某个具体的注解bean加上ID值 创建一个对象
@Service(“UserService”)

6.5 具体实现

6.5.1 实体类 UserInfo.java

package com.hnxy.entity;

import java.util.Date;
/**
 * 以OOP思想为基础
 * @author My
 *
 */
public class UserInfo {

	// 私有属性	
	private Integer uid;		// 主键ID
	private String uname;		// 客户姓名
	private Date regDate;		// 注册时间
	private Double money;		// 用户余额
		
	// 共有方法	
	public Integer getUid() {
		return uid;
	}
	public void setUid(Integer uid) {
		this.uid = uid;
	}
	public String getUname() {
		return uname;
	}
	public void setUname(String uname) {
		this.uname = uname;
	}
	public Date getRegDate() {
		return regDate;
	}
	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}
	public Double getMoney() {
		return money;
	}
	public void setMoney(Double money) {
		this.money = money;
	}
	@Override
	public String toString() {
		return "UserInfo [uid=" + uid + ", uname=" + uname + ", regDate=" + regDate + ", money=" + money + "]";
	}
}

6.5.2 Spring配置文件 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans 
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	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.xsd
        ">
	
	<!-- 配置注解bean的包扫描器 -->
	<context:component-scan base-package="*.*.dao" />
	<context:component-scan base-package="*.*.service" />
	<!-- 需要一个数据源对象 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://127.0.0.1:3306/userdb?characterEncoding=UTF-8" />
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>
	<!-- 创建SQL的执行对象 -->
	<bean id="qr" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
		<!-- 构造函数创建对象 -->
		<constructor-arg name="ds" ref="dataSource" />
	</bean>
</beans>

6.5.3 改造的实现类 DAOImpl

package com.hnxy.dao.impl;

import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import com.hnxy.dao.UserDAO;
import com.hnxy.entity.UserInfo;

/**
 * UserDAO接口的实现类
 * @author My
 * @Component = <bean id="UserDAOImpl" class="类的全限定名字">
 * @Component("userDAO")  = <bean id="userDAO" class="类的全限定名称">
 * @Repository 继承于 @Component 专门用来标记DAO层bean的一个注解
 * 约定 : @Repository只能用于DAO层
 */
@Repository
public class UserDAOImpl implements UserDAO {
	
	// DAO层到底需要哪些个对象才能完成这个需求? DAO 操作数据库 执行SQL语句
	// 数据源(c3p0)-->SQL执行对象(dbutils queryrunner)
	// @Autowired 代表这个属性自动按照类型注入
	
	@Autowired
	private QueryRunner qr;


	@Override
	public int findUserByPageListCount() throws Exception {
		// 创建方法的返回值
		int totalCount = 0;
		// 编写SQL语句
		String sql = "select count(*) from v1";
		// 占位符赋值
		// 执行
		Number num = qr.query(sql, new ScalarHandler<Number>(1));
		// 处理返回值
		totalCount = num.intValue();
		// 返回
		return totalCount;
	}

	@Override
	public List<UserInfo> findUserByPageList(Integer start, Integer size) throws Exception {
		// 创建方法的返回值
		List<UserInfo> list = null;
		// 创建SQL语句
		String sql = "select * from v1 limit ?,?";
		// 占位符赋值
		Object[] params = {start,size};
		// 执行
		list = qr.query(sql, new BeanListHandler<UserInfo>(UserInfo.class),params);
		// 返回
		return list;
	}

	@Override
	public UserInfo findUserByID(Integer uid) throws Exception {
		// 创建方法的返回值
		UserInfo user = null;
		// 创建SQL语句
		String sql = "select * from v1 where uid = ?";
		// 占位符赋值
		Object[] params = {uid};
		// 执行
		user = qr.query(sql, new BeanHandler<UserInfo>(UserInfo.class),params);
		// 返回
		return user;
	}

	@Override
	public int insertUser(UserInfo user) throws Exception {
		// 创建方法的返回值
		int count = 0;
		// 创建SQL语句
		String sql = "insert into user_info values (null,?,?,?)";
		// 占位符赋值
		Object[] params = {user.getUname(),user.getRegDate(),user.getMoney()};
		// 执行
		count = qr.update(sql,params);
		// 返回
		return count;
	}

	@Override
	public int updateUser(UserInfo user) throws Exception {
		// 创建方法的返回值
		int count = 0;
		// 创建SQL语句
		String sql = "update user_info set u_name=?,u_regdate=?,u_money=? where u_id = ?";
		// 占位符赋值
		Object[] params = {user.getUname(),user.getRegDate(),user.getMoney(),user.getUid()};
		// 执行
		count = qr.update(sql,params);
		// 返回
		return count;
	}

	@Override
	public int deleteUser(UserInfo user) throws Exception {
		// 创建方法的返回值
		int count = 0;
		// 创建SQL语句
		String sql = "delete from user_info where u_id = ?";
		// 占位符赋值
		Object[] params = {user.getUid()};
		// 执行
		count = qr.update(sql,params);
		// 返回
		return count;
	}
}

6.5.4 ServiceImpl

package com.hnxy.service.impl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hnxy.dao.UserDAO;
import com.hnxy.entity.UserInfo;
import com.hnxy.service.UserService;

@Service
public class UserServiceImpl implements UserService {
	
	@Autowired
	private UserDAO userDAO;
	

	@Override
	public int findUserByPageListCount() throws Exception {
		return userDAO.findUserByPageListCount();
	}

	@Override
	public List<UserInfo> findUserByPageList(Integer pageIndex, Integer pageSize) throws Exception {
		List<UserInfo> list = null;
		if(null != pageIndex && null != pageSize){
			if(pageIndex > 0 && pageSize > 0){
				list = userDAO.findUserByPageList((pageIndex-1)*pageSize, pageSize);
			}
		}
		// 返回
		return list;
	}

	@Override
	public UserInfo findUserByID(Integer uid) throws Exception {
		return userDAO.findUserByID(uid);
	}

	@Override
	public int insertUser(UserInfo user) throws Exception {
		return userDAO.insertUser(user);
	}

	@Override
	public int updateUser(UserInfo user) throws Exception {
		return userDAO.updateUser(user);
	}

	@Override
	public int deleteUser(UserInfo user) throws Exception {
		return userDAO.deleteUser(user);
	}
}

6.6 注解bean的配置总结

  1. 注解bean的配置 只针对我们自己写的类 注解可不可以配置在接口上?接口不可以配置注解bean! 为啥?因为接口不能new

  2. 一定要记住
    Service的bean 怎么配置注解 @Service
    DAO中的bean 怎么配置注解 @Repository
    注意 我们这么配置注解的话 其实 就相当于配置了一个 <bean class=""> 没有配置id 所以我们在获取这个bean的对象的时候 用 类型获取

  3. 如果你想给某个bean下的属性进行赋值 那么你应该使用 @Autowired
    而且此处需要注解 当你使用 @Autowired注解的时候 你是不用给属性提供set方法

  4. 注解配置完的bean 散落在了不同的包里 那么spring要想组织这些信息 它必须知道这些bean都在哪?
    在这里插入图片描述
    后我们一定要注意一个问题 :

在大多数同学些 Spring注解的时候 经常忘记写@Repository,@Service
我们以后再编写类的时候这两个注解一定要先 千万不要忘了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值