雖然Spring管理這我們的Bean很方便,但是,我們需要使用xml配置大量的Bean信息,告訴Spring我們要幹嘛,這還是挺煩的,畢竟當我們的Bean隨之增多的話,xml的各種配置會讓人很頭疼。
所以我們需要一種東西來解決這個問題,這就是——註解,這次我們使用註解來將我們學過的所有東西重新做過一遍。
1. 了解註解
1.1 定義
註解是JDK1.5及以後版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,註釋。
1.2 組成
- 元註解
包括@Retention、@Target、@Document、@Inherited四種 - jdk註解
包括@Override、@Deprecated、@SuppressWarnings - 自定義註解
自定義註解就是通過一定的規範,通過編寫代碼實現的
這裏有幾篇博文可供大家參考,其實了解註解可以讓自己使用Spring的註解時不會很詫異,所以了解一下還是有好處的
http://www.cnblogs.com/Qian123/p/5256084.html
http://www.importnew.com/14479.html
http://www.cnblogs.com/yejg1212/p/3187362.html
http://www.cnblogs.com/lyy-2016/p/6288535.html
2. 加入maven依賴
這裏的依賴於上篇博客的並沒有什麽不同之處,依賴主要如下:
<properties>
<spring.version>4.3.10.RELEASE</spring.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-Java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies>
3. Spring配置文件
添加了相關的依賴後我們現在就要對Spring進行配置了,以下便是classpath下的applicationContext.xml
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!--開啟aspect註解-->
<aop:aspectj-autoproxy />
<!--加載db.properties配置文件-->
<context:property-placeholder location="db.properties"/>
<!--掃描包下的所有類,遇到相關註解會進行一些註冊工作-->
<context:component-scan base-package="cn.lger"/>
<!--開啟註解-->
<context:annotation-config/>
<!--配置DataSource-->
<bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--以下是數據庫連接的具體信息 通過表達式將db.properties的信息註入-->
<property name="username" value="http://www.cnblogs.com/lger/p/${jdbc.username}"/>
<property name="password" value="http://www.cnblogs.com/lger/p/${jdbc.password}"/>
<property name="driverClassName" value="http://www.cnblogs.com/lger/p/${jdbc.driver}"/>
<property name="url" value="http://www.cnblogs.com/lger/p/${jdbc.url}"/>
</bean>
<!--註冊事務管理類-->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--開啟事務註解 註解添加事務管理類映射-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
上面的配置文件當中跟之前有所不同的就是添加了context約束,還有利用context加載了db.properties
,這是有關數據庫的相關配置,之前是直接在配置文件寫入,現在進行了提取,然後利用了context進行加載。
db.properties文件也是置於classpath下,具體內容是
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_demo_1
jdbc.username=root
jdbc.password=root
4. 使用註解裝配Bean
好,經過上面的折騰之後就可使用註解開發我們程序了,接下來進入主題。
現在有一個場景,就是一個人擁有一只小狗叫旺財,如果參考之前的博客我的Spring學習記錄(二)就會發現我們需要配置的東西很多,現在我們用全新的方式來裝配我們的Bean。現在我們給出實體,如下:
//這裏為Man的超類,方便之後引申一些東西實現多態
public abstract class Human {
public abstract String myNameIs();
}
//註冊為Spring的Bean Bean的名字叫man
@Component(value = "http://www.cnblogs.com/lger/p/man")
public class Man extends Human{
@Value(value = "http://www.cnblogs.com/lger/p/張三")
private String name;
//自動將Spring容器中Dog類型的Bean裝配到dog
@Autowired
private Dog dog;
public String getUsername() {
return name;
}
public void setUsername(String username) {
this.name = username;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String myNameIs() {
return name;
}
public void noFreeTime(){
system.out.println("狗主人沒有時間(public void noFreeTime())");
}
@Override
public String toString() {
return "Man{" +
"name='" + name + '\'' +
", dog=" + dog +
'}';
}
}
//註冊為Spring的Bean
@Component(value = "http://www.cnblogs.com/lger/p/dog")
public class Dog {
//註入值
@Value(value = "http://www.cnblogs.com/lger/p/旺財")
private String name;
@Value(value = "http://www.cnblogs.com/lger/p/土狗")
private String breed;
@Value(value = "http://www.cnblogs.com/lger/p/公")
private String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", breed='" + breed + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
有了上面的準備工作之後,我們可以對我們的代碼進行簡單的測試了,我們現在不使用ClassPathXmlApplicationContext
來加載我們的Bean了,而是使用Spring test,同樣的利用註解可以剩下很多事情,代碼主要如下:
//junit運行的時候就會加載 SpringJUnit4ClassRunner,
//SpringJUnit4ClassRunner是Spring test提供的主要是方便測試
@RunWith(SpringJUnit4ClassRunner.class)
//加載Spring 配置文件
@ContextConfiguration("classpath:applicationContext.xml")
public class TestWired {
@Autowired
private Man man;
/**
* 測試註解裝配是否成功
*/
@Test
public void test01(){
System.out.println(man);
}
}
//打印結果:Man{username='張三', money=9600.0, dog=Dog{name='旺財', breed='土狗', sex='公'}}
5. 使用註解完成AOP
現在我們的 Man
沒有時間去看管我們的狗狗 Dog
了,迫切地需要找到一個幫忙照看狗狗的代理人 Proxy
,讓他幫忙照看遛狗,Proxy
的代碼實現如下:
@Aspect
//這裏必須註冊為Spring的Bean,雖然有了Aspect
//但是需要Spring調用這個切面還是需要註冊為Spring的組件
@Component
public class Proxy {
@Pointcut("execution(* cn.lger.domain.Man.noFreeTime())")
public void noFreeTime(){}
@Before(value = "http://www.cnblogs.com/lger/p/noFreeTime()")
public void before(){
System.out.println("代理人去被代理人家裏牽狗,然後遛狗");
}
@After(value = "http://www.cnblogs.com/lger/p/noFreeTime()")
public void after(){
System.out.println("代理人帶狗狗回家");
}
}
看到了上面的代碼之後想想我們之前使用xml配置切面是不是很簡單了。
接下來我們測試一下我們的AOP是否能夠成功
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestAspect {
@Autowired
private Man man;
@Test
public void test01(){
man.noFreeTime();
}
}
//打印結果: 代理人去被代理人家裏牽狗,然後遛狗
// 狗主人沒有時間(public void noFreeTime())
// 代理人帶狗狗回家
通過以上的測試我們基本上可以知道,與我們之前使用xml配置的AOP並沒有什麽結果上的不同,成功。
6. 使用註解完成Spring事務
好,通過AOP後我們接下來的就是利用AOP實現的Spring聲明式事務
首先這裏有 dao
和 service
@Component
public class TransferDao extends JdbcTemplate {
/**
* 將錢的數目轉向當前user的賬戶
* @param money money
* @param username username
*/
public void transferMoneyToOne(Float money, String username){
this.update("UPDATE account SET money = money + (?) WHERE username = ?", money, username);
}
/**
* 通過有參構造函數註入DataSource
* @param dataSource dataSource
*/
@Autowired
public TransferDao(DataSource dataSource){
//因為沒用xml註入dataSource所以這裏需要自己設置
//調用超類的構造函數設置dataSource
super(dataSource);
}
}
@Component
public class TransferService {
@Autowired
private TransferDao dao;
/**
* 轉賬業務,這裏為了方便直接寫了張三轉給了李四100塊錢
*/
@Transactional
public void transferMoney(){
dao.transferMoneyToOne((float) -100, "張三");
// int i = 1 / 0;//這裏模仿轉賬過程中可能出現的異常,測試時可以去掉註釋用於測試事務是否成功執行
dao.transferMoneyToOne((float) 100, "李四");
// throw new RuntimeException("這裏突然死機了");
}
public TransferDao getDao() {
return dao;
}
public void setDao(TransferDao dao) {
this.dao = dao;
}
}
下面我們進行測試工作來看看代碼是否能夠成功執行事務性的操作
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestTransaction {
@Autowired
private TransferService transferService;
/**
* 測試轉賬事務
*/
@Test
public void test01(){
transferService.transferMoney();
}
}
經過我們的測試證明當沒有出現異常的情況張三成功給了李四轉賬了,當我們去掉註釋出現異常結果是轉賬不成功。註解式的Spring事務配置就先是這麽多
7. 總結
註解替代我們的xml配置可以幫助我們節省下很多的開發步驟,提高我們的開發效率,但是註解也是有一定的缺陷的,比如有沒有覺得我們好好的xml把所有的東西都放在一起看著就能夠集中一點,而註解就是相對的分散,這樣可能我們維護的時候就會在各個類直接的註解中轉來轉去。所以各有各的好處。
Spring的註解遠遠不止是這麽多,比如裝配我們的Bean的Autowired在某種情況下就會出錯,比如我們多態的實現,有兩個子類作為組件,那麽它要註入哪個?? 所以需要一個東西去輔助它,聲明是哪一個Bean要被註入,除了Autowired裝配還有Resource、Inject等;
裝配之外還有其他的註解都需要學習一下,但是這篇的長度就會很長很長了,所以我就沒有詳細的寫明,我給出一些鏈接,希望給大家的學習節省一些時間,如果之後我閑著的時候我將會以這篇為導引,寫多一些註解來一起學習
Spring註解相關博文
http://blog.csdn.net/xyh820/article/details/7303330/
http://blog.csdn.net/u010987379/article/details/52152795
http://www.cnblogs.com/szlbm/p/5512931.html
http://blog.csdn.net/zheng0518/article/details/49206847
http://blog.csdn.net/lindonglian/article/details/47043727
http://www.cnblogs.com/biehongli/p/6640406.html
以上的代碼可以在Github下載
Tags: 註解 我們 Spring com 依賴 定義
文章來源: