虽然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="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${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 = "man")
public class Man extends Human{ @Value(value = "张三")
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 = "dog")
public class Dog { //注入值
@Value(value = "旺财")
private String name;
@Value(value = "土狗")
private String breed;
@Value(value = "公")
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 = "noFreeTime()")
public void before(){
System.out.println("代理人去被代理人家里牵狗,然后遛狗");
} @After(value = "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声明式事务

首先这里有 daoservice

@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下载

我的Spring学习记录(四)的更多相关文章

  1. Spring学习记录(四)---bean之间的关系:继承、依赖

         继承 这里说的继承和java的继承是不一样的,不是父类子类.但思想很相似,是父bean和子bean 1.父bean是一个实例时.它本身是一个完整的bean 2.父bean是模板,抽象bean ...

  2. 我的Spring学习记录(五)

    在我的Spring学习记录(四)中使用了注解的方式对前面三篇做了总结.而这次,使用了用户登录及注册来对于本人前面四篇做一个应用案例,希望通过这个来对于我们的Spring的使用有一定的了解. 1. 程序 ...

  3. Spring 学习记录3 ConversionService

    ConversionService与Environment的关系 通过之前的学习(Spring 学习记录2 Environment),我已经Environment主要是负责解析properties和p ...

  4. Spring 学习记录8 初识XmlWebApplicationContext(2)

    主题 接上文Spring 学习记录7 初识XmlWebApplicationContext refresh方法 refresh方法是定义在父类AbstractApplicationContext中的. ...

  5. spring 学习(四): spring 的 jdbcTemplate 操作

    spring 学习(四): spring 的 jdbcTemplate 操作 spring 针对 javaee 的每一层,都提供了相应的解决技术,jdbcTemplate 的主要操作在 dao 层. ...

  6. 我的Spring学习记录(二)

    本篇就简单的说一下Bean的装配和AOP 本篇的项目是在上一篇我的Spring学习记录(一) 中项目的基础上进行开发的 1. 使用setter方法和构造方法装配Bean 1.1 前期准备 使用sett ...

  7. leveldb 学习记录(四)Log文件

    前文记录 leveldb 学习记录(一) skiplistleveldb 学习记录(二) Sliceleveldb 学习记录(三) MemTable 与 Immutable Memtablelevel ...

  8. Spring 学习记录6 BeanFactory(2)

    主题 除了Spring 学习记录5 BeanFactory 里写的几个接口外,BeanFactory的实现类还实现了一些其他接口,这篇文章主要介绍这些接口和实现类. 结构 DefaultListabl ...

  9. JavaScript学习记录四

    title: JavaScript学习记录四 toc: true date: 2018-09-16 20:31:22 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...

随机推荐

  1. 如何快速的理解JavaScript闭包?

    先看问题 1. 在js中的作用域是什么? 作用域就是作用范围,作用空间.作用域分为全局作用域和局部作用域.(这个东西大家都明白) 如果把局部作用域比作一个国家,那么全局作用域就是地球,地球上除了那个国 ...

  2. Android WebView基本使用

    转载请注明出处: http://blog.csdn.net/lowprofile_coding/article/details/77928614 WebView介绍 Android WebView在A ...

  3. 使用CXF开发JAX-RS类型的WebService

    1.JAXRSServerFactoryBean编程方式 访问方式:http://localhost:8080/cxf_spring_rest_server/ws/rest/student/query ...

  4. [自制操作系统] 连续页分配释放&kmalloc/kfree

    本文将在JOS上实现连续内存.释放,提供内核的kmalloc与kfree,并在分配frambuffer的时候进行测试. Github : https://github.com/He11oLiu/JOS ...

  5. sublime中如何在浏览器中打开文件?

    SideBarEnhancements 侧边栏增强 SideBarEnhancements本是增强侧边栏的插件,这里将教大家如何用来做sublime text 3浏览器预览插件,并可自定义浏览器预览的 ...

  6. Linux cat /proc/meminfo 输出分析

    $cat /proc/meminfoMemTotal:        2052440 kB //总内存MemFree:           50004 kB //空闲内存Buffers:        ...

  7. 四则运算 WEB

    coding.net:https://git.oschina.net/ysh0904/WEB.git 一.需求分析 记录用户的对错总数,程序退出再启动的时候,能把以前的对错数量保存并在此基础上增量计算 ...

  8. 微信小程序中的微信支付js代码和流程详解

    微信支付流程 步骤 (一)获取用户的信息 (二)统一下单(返回的prepay_id用于第(三)步的请求参数) (三)发起支付请求 操作(这边假设你已经获得了用户的openId) (一).获取用户ope ...

  9. 201521123028 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2. 书面作业 Q1.clone方法 1.1 Object ...

  10. 201521123089 《Java程序设计》第1周学习总结

    1. 本周学习总结 学习了java的发展史以及JDK,JVM,JRE; 2. 书面作业 1.为什么java程序可以跨平台运行?执行java程序的步骤是什么? java有JVM,实在虚拟机上运行的. 2 ...