這是個系列教程串远,看完這個,你對JavaEE注解瑞凑,包括spring、hibernate概页,RESTFul web service 籽御,JAXB, 以及junit注解將會有一個全面的了解。
英文原版網(wǎng)址在這里 我們不光是spring網(wǎng)站的搬運(yùn)工@農(nóng)夫山泉水,實(shí)際上技掏,翻譯過程中我保證準(zhǔn)確同時铃将,加入了自己的理解。
** Spring Annotations 列表: **
@Service
import org.springframework.stereotype.Service;
@Repository
import org.springframework.stereotype.Repository;
@Component
import org.springframework.stereotype.Component;
@Autowired
import org.springframework.beans.factory.annotation.Autowired;
@Transactional
import org.springframework.transaction.annotation.Transactional;
@Scope
import org.springframework.context.annotation.Scope;
以及
@Controller
import org.springframework.stereotype.Controller;
@RequestMapping
import org.springframework.web.bind.annotation.RequestMapping;
@PathVariable
import org.springframework.web.bind.annotation.PathVariable;
@RequestParam
import org.springframework.web.bind.annotation.RequestParam;
@ModelAttribute
import org.springframework.web.bind.annotation.ModelAttribute;
@SessionAttributes
import org.springframework.web.bind.annotation.SessionAttributes;
Spring Security Annotations
@PreAuthorize
import org.springframework.security.access.prepost.PreAuthorize;
首先看一下一個典型的Java web項(xiàng)目結(jié)構(gòu):
part1. Spring Annotations
@Service 用在所有業(yè)務(wù)邏輯代碼類中哑梳,對應(yīng)圖中service package下的類
@Service
public class UserServiceImpl implements UserService{
}
@Repository用在領(lǐng)域類劲阎,對應(yīng)三層的DAO層(數(shù)據(jù)庫操作類),上圖 的domain package:
@Repository
public interface UserRepo extends JpaRepository<User,Integer> {
User findByName(String name);
}
@Component用在其它組件(無法分類的鸠真,如工具類)
實(shí)際上悯仙,Component注解和其它注解有如下關(guān)系:
@Autowired
自動織入其他bean到你的類中(Ioc,Spring精髓)
@Service
public class CompanyServiceImpl implements CompanyService {
@Autowired
private CompanyDAO companyDAO;
...
}
@Transactional
開啟事務(wù)
@Service
public class CompanyServiceImpl implements CompanyService {
@Autowired
private CompanyDAO companyDAO;
//開啟事務(wù)后吠卷,當(dāng)此方法出錯锡垄,數(shù)據(jù)將會回滾
//比如,連續(xù)添加10條數(shù)據(jù)祭隔,第7條出錯货岭,則最后一條都不會添加,若
//不加Trsanctional序攘,則會添加6條
@Transactional
public Company saveName(Company comp) {
Company company = companyDAO.save(comp);
return company;
}
}
@Scope:
這個首先看一下spring中scope定義:
** scope概論**
spring中scope是一個非常關(guān)鍵的概念茴她,簡單說就是對象在spring容器(IOC容器)中的生命周期寻拂,也可以理解為對象在spring容器中的創(chuàng)建方式程奠。
scope歷史及分類
目前,scope的取值有5種取值:
在Spring 2.0之前祭钉,有singleton和prototype兩種瞄沙;
在Spring 2.0之后,為支持web應(yīng)用的ApplicationContext慌核,增強(qiáng)另外三種:request距境,session和global session類型,它們只實(shí)用于 web程序垮卓,通常是和XmlWebApplicationContext共同使用垫桂。
單個scope詳解
- singleton (單一實(shí)例)
此取值時表明容器中創(chuàng)建時只存在一個實(shí)例,所有引用此bean都是單一實(shí)例粟按。如同每個國家都有一個總統(tǒng)诬滩,國家的所有人共用此總統(tǒng),而這個國家就是一個spring容器灭将,總統(tǒng)就是spring創(chuàng)建的類的bean疼鸟,國家中的人就是其它調(diào)用者,總統(tǒng)是一個表明其在spring中的scope為singleton庙曙,也就是單例模型空镜。
此外,singleton類型的bean定義從容器啟動到第一次被請求而實(shí)例化開始,只要容器不銷毀或退出吴攒,該類型的bean的單一實(shí)例就會一直存活张抄,典型單例模式,如同servlet在web容器中的生命周期洼怔。
2)prototype
spring容器在進(jìn)行輸出 prototype的bean 對象時欣鳖,會每次都重新生成一個新的對象給請求方,雖然這種類型的對象的實(shí)例化以及屬性設(shè)置等工作都是由容器負(fù)責(zé)的茴厉,但是只要準(zhǔn)備完畢泽台,并且對象實(shí)例返回給請求方之后,容器就不在擁有當(dāng)前對象的引用矾缓,請求方需要自己負(fù)責(zé)當(dāng)前對象后繼生命周期的管理工作怀酷,包括該對象的銷毀。也就是說嗜闻,容器每次返回請求方該對象的一個新的實(shí)例之后蜕依,就由這個對象“自生自滅”,最典型的體現(xiàn)就是spring與struts2進(jìn)行整合時琉雳,要把a(bǔ)ction的scope改為prototype样眠。
如同分蘋果,將蘋果的bean的scope屬性聲明為prototype翠肘,在每個人領(lǐng)取蘋果的時候檐束,我們都是發(fā)一個新的蘋果給他,發(fā)完之后束倍,別人愛怎么吃就怎么吃被丧,愛什么時候吃什么時候吃,但是注意吃完要把蘋果核扔到垃圾箱绪妹!對于那些不能共享使用的對象類型甥桂,應(yīng)該將其定義的scope設(shè)為prototype。
3)request
再次說明 request邮旷,session和global session類型只實(shí)用于 web程序黄选,通常是和XmlWebApplicationContext共同使用。
<bean id ="requestPrecessor" class="...RequestPrecessor" scope="request" />
Spring容器婶肩,即XmlWebApplicationContext 會為每個HTTP請求創(chuàng)建一個全新的RequestPrecessor對象办陷,當(dāng)請求結(jié)束后,該對象的生命周期即告結(jié)束狡孔, **如同java web中request的生命周期 **懂诗。 當(dāng)同時有100個HTTP請求進(jìn)來的時候,容器會分別針對這10個請求創(chuàng)建10個全新的RequestPrecessor實(shí)例苗膝,且他們相互之間互不干擾殃恒, 簡單來講植旧, request可以看做prototype的一種特例 ,除了場景更加具體之外离唐,語意上差不多病附。
4)session
對于web應(yīng)用來說,放到session中最普遍的就是用戶的登錄信息亥鬓,對于這種放到session中的信息完沪,我們可以使用如下形式的制定scope為session:
<bean id ="userPreferences" class="...UserPreferences" scope="session" />
Spring容器會為每個獨(dú)立的session創(chuàng)建屬于自己的全新的UserPreferences實(shí)例,比request scope的bean會存活更長的時間嵌戈,其他的方面沒區(qū)別覆积, 如果java web中session的生命周期 。
5)global session
<bean id ="userPreferences" class="...UserPreferences" scope="globalsession" />
global session只有應(yīng)用在基于porlet的web應(yīng)用程序中才有意義熟呛,它映射到porlet的global范圍的session宽档,如果普通的servlet的web 應(yīng)用中使用了這個scope,容器會把它作為普通的session的scope對待庵朝。
@Scope聲明現(xiàn)在就能看懂了吧
@Component
@Scope("request")
public class ContactResource {
...
}
part 2 . Spring MVC Annotations
@Controller, @RequestMapping,@PathVariable,@RequestParam這幾個太常用了吗冤,來不及解釋了,補(bǔ)充一點(diǎn)就是還可以使用 @RequestHeader獲得header信息
@ModelAttribute是java中的數(shù)據(jù)綁定九府,用于將表單對應(yīng)項(xiàng)綁定到模型
@Controller
@RequestMapping("/company")
public class CompanyController {
@Autowired
private CompanyService companyService;
@RequestMapping("/add")
public String saveNewCompany(@ModelAttribute Company company) {
companyService.add(company);
return "redirect:" + company.getName();
}
...
}
@SessionAttributes就是保存session椎瘟,定義在一個Controller類上
@RestController
@RequestMapping("/user")
@SessionAttributes("currUser")
public class UserController {
@Autowired
private UserRepo userRepo;
@Transactional
@RequestMapping("/save")
public User save(User user){
User newUser = userRepo.save(user);
return newUser;
}
}
SessionAttributes 可以和ModelAttribute結(jié)合使用, 我們可以在需要訪問 Session 屬性的 controller 上加上 @SessionAttributes侄旬,然后在 action 需要的 User 參數(shù)上加上 @ModelAttribute肺蔚,并保證兩者的屬性名稱一致。
@Controller
@SessionAttributes("currentUser")
public class GreetingController{
@RequestMapping
public void hello (@ModelAttribute("currentUser") User user){
//user.sayHello()
}
}
一個綜合以上的實(shí)例:
@Controller
@RequestMapping("/owners/{ownerId}/pets/{petId}/edit")
@SessionAttributes("pet")
public class EditPetForm {
@ModelAttribute("types")
public Collection<PetType> populatePetTypes() {
return this.clinic.getPetTypes();
}
@RequestMapping(method = RequestMethod.POST)
public String processSubmit(@ModelAttribute("pet") Pet pet,
BindingResult result, SessionStatus status) {
new PetValidator().validate(pet, result);
if (result.hasErrors()) {
return "petForm";
}else {
this.clinic.storePet(pet);
status.setComplete();
return "redirect:owner.do?ownerId="
+ pet.getOwner().getId();
}
}
}
@PreAuthorize:預(yù)檢查
@Transactional
@PreAuthorize("hasRole('ROLE_ADMIN')")
public void removeContact(Integer id) {
contactDAO.removeContact(id);
}