虽然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. Django连接mysql数据库

    1.app中对应的models.py配置相关表结构信息 from django.db import models class Question(models.Model): question_text ...

  2. JAVA定时任务实现的几种方式

    近日项目开发中需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息,借此机会整理了一下定时任务的几种实现方式,由于项目采用spring框架,所以我都将结合spring框架来介绍. 一 ...

  3. [转载]GIF、JPEG 和 PNG的区别在哪里?

    原文地址:GIF.JPEG 和 PNG的区别在哪里?作者:苗得雨 GIF.JPEG 和 PNG 是三种最常见的图片格式. GIF:1987 年诞生,常用于网页动画,使用无损压缩,支持 256 种颜色( ...

  4. springboot配置swagger2

    .在pom.xml里添加jar包: <dependency> <groupId>io.springfox</groupId> <artifactId>s ...

  5. 201521123080《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. (1)继承:子类继承父类,子类可以复用父类的方法和函数. (2)多态:方法的重写和重载是Ja ...

  6. 第2周作业-Java基本语法与类库(20170227-20170304)

    本周学习总结 (1)这周学习认识和熟悉了java的一些类型和变量: (2)学习了java的运算符基本使用方法: (3)了解了如何建立远程仓库和本地仓库,和如何让java代码在临时储存,本地仓库和远程仓 ...

  7. 一个Markdown的例子

    一个例子: 例子开始 1. 本章学习总结 今天主要学习了三个知识点 封装 继承 多态 2. 书面作业 Q1. java HelloWorld命令中,HelloWorld这个参数是什么含义? 今天学了一 ...

  8. 通过SDK和API获取阿里云RDS的监控数据

    阿里云的RDS自带的监控系统获取数据不怎么直观,想要通过API获取数据通过zabbix显示,因为网上资料缺乏和其他一些原因,获取API签名很困难,但使用阿里云的SDK可以完美避开获取签名的步骤. 阿里 ...

  9. 磁盘管理之inode与block

    索引式文件系统 什么是inode? Inode其实就是索引号,便于我们寻找我们文件所存储的数据块block,索引式文件系统在查找信息,读写操作上都比原来的文件系统要快,我们可以通过inode中记录的b ...

  10. Mybatis第七篇【resultMap、resultType、延迟加载】

    resultMap 有的时候,我们看别的映射文件,可能看不到以下这么一段代码: <resultMap id="userListResultMap" type="us ...