1. 程式人生 > >Java自學之路-Java中級教程-9:Spring自動掃描注入component-scan以及@Service註解

Java自學之路-Java中級教程-9:Spring自動掃描注入component-scan以及@Service註解

Spring的@Autowired註解可以實現自動裝配,即不需要在xml中再顯式地注入依賴。

前面幾節的資料庫訪問類PersonDataAccessObject實際上已有dataSource和jdbcTemplate兩種實現,為了能夠繼續使用兩種方式,可以給PersonDataAccessObject定義一個介面,名為PersonDao,然後把dataSource和jdbcTemplate兩種實現分別定義兩個實現介面的類PersonDataSourceDaoImpl及PersonJdbcTemplateDaoImpl。

package com.helloworld.dao;

import java.util.List;

import com.helloworld.Person;

public interface PersonDao {

	public List getPersonList();
}
package com.helloworld.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import com.helloworld.Person;

public class PersonDataSourceDaoImpl implements PersonDao {

	private DataSource dataSource;

	public DataSource getDataSource() {
		return dataSource;
	}

	public List getPersonList() throws Exception {

		Connection conn = dataSource.getConnection();

		Statement stmt = conn.createStatement();
		ResultSet rs = stmt.executeQuery("select * from new_table");

		List personList = new ArrayList();
		while (rs.next()) {
			Person person = new Person();
			person.setId(rs.getInt(1));
			person.setNation(rs.getString(2));

			personList.add(person);

		}

		if (rs != null) {
			rs.close();
		}
		if (stmt != null) {
			stmt.close();
		}
		if (conn != null) {
			conn.close();
		}

		return personList;

	}

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}

}
package com.helloworld.dao;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.JdbcTemplate;

import com.helloworld.Person;

public class PersonJdbcTemplateDaoImpl implements PersonDao {

	private JdbcTemplate jdbcTemplate;

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	public List getPersonList() throws Exception {

		List rowList = jdbcTemplate.queryForList("select * from new_table");

		List personList = new ArrayList();
		Iterator it = rowList.iterator();
		while (it.hasNext()) {
			Person person = new Person();

			Map personrMap = (Map) it.next();
			person.setId((Integer) personrMap.get("id"));
			person.setNation((String) personrMap.get("nation"));

			personList.add(person);

		}

		return personList;

	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

}

在applicationContext-dao.xml檔案中,可以注入兩個不同的Dao實現personJdbcTemplateDao和personDataSourceDao。

在SpringContextMain的main()方法中,無論獲取哪一個實現,都可以強轉為PersonDao,用介面的方式來呼叫查詢列表方法personDao.getPersonList()。

ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/helloworld/dao/applicationContext-dao.xml");
PersonDao personDao = (PersonDao) ac.getBeanFactory().getBean("personJdbcTemplateDao");

List personList = personDao.getPersonList();
 

personDao = (PersonDao) ac.getBeanFactory().getBean("personDataSourceDao");

List personList2 = personDao.getPersonList();

無論是注入DataSource還是JdbcTemplate,都要生成setter和getter方法。這是因為Spring就是通過setter和getter方法來注入依賴的例項和得到注入的例項。

public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
 

public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
 

這裡的Dao即是資料訪問物件(Data Access Object),Person即是資料模型物件(Model)。在Web程式設計中有一個MVC模式的概念,其中的M即是這裡的Model。MVC模式講究分層次設計,把應用程式大致分為Model層、View層、Controller層,即資料模型層、表現層、控制層。

從分層的角度來說,Dao資料訪問層一般不直接給外界使用,而是在中間封裝一層Service業務層,由Service呼叫資料訪問層的實現,並在Service中用資料訪問層得到的資料模型來再處理一些複雜的業務。

新建一個類PersonService,所在包名為com.helloworld.service。在PersonService新建helpToDo(),並注入PersonDao的依賴。

package com.helloworld.service;

import java.util.List;

import com.helloworld.Hand;
import com.helloworld.Person;
import com.helloworld.dao.PersonDao;

public class PersonService {

	private PersonDao personDao;

	public PersonDao getPersonDao() {
		return personDao;
	}

	public void setPersonDao(PersonDao personDao) {
		this.personDao = personDao;
	}

	public List helpToDo() throws Exception {
		List personList = personDao.getPersonList();
		for (Person person : personList) {
			Hand hand = person.getHand();
			// 讓每個Person幫手做一些事...
			if (hand != null) {
				System.out.println(hand.toString());
			} else {
				System.out.println("No hand!");
			}

		}
		return personList;
	}

}

這樣,Service可以使用Dao取到的資料進行一些業務處理。至於使用Dao的哪個實現,可以在xml中進行注入,比如注入bean id="personService" class="com.helloworld.dao.PersonService",再注入屬性property name="personDao" ref="personJdbcTemplateDao"。

在SpringContextMain可以改用獲取PersonService的物件例項,並呼叫方法personService.helpToDo()來處理業務上的事。

PersonService personService = (PersonService) ac.getBeanFactory().getBean("personService");
personService.helpToDo();

如果只想保留com.helloworld.dao.PersonJdbcTemplateDaoImpl的實現,還可以直接注入一個bean id="personDao" class="com.helloworld.dao.PersonJdbcTemplateDaoImpl",直接讓Service拿到這個實現來用。

這樣只保留了Dao的一種實現,也就是Service中依賴的就是com.helloworld.dao.PersonJdbcTemplateDaoImpl。

前面使用了@Autowired和@Component註解,可以省略在xml中注入這些bean,所以完全可以使用註解來給Service注入Dao。

在applicationContext-dao.xml中加入context的宣告xmlns:context="http://www.springframework.org/schema/context"以及http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd
並且注入一個context:component-scan base-package="com.helloworld"的標籤,意思是在com.helloworld包中掃描@Component的類來生成註解的例項。在需要註解的類上,加上相應的註解@Component和@Autowired,而在PersonService類上加入@Service註解,表明這是一個Service。

@Component
public class PersonJdbcTemplateDaoImpl implements PersonDao {

@Autowired
private JdbcTemplate jdbcTemplate;
}

@Service
public class PersonService {

@Autowired
private PersonDao personDao;
}

如此一來,xml中只有jdbcTemplate和dataSource的配置了,配置簡潔了許多。

配套進階視訊教程:

Java中级SSHæ¡æ¶é¡¹ç®å¼å设计æç¨

Java視訊教程