虽然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. CSS-三栏响应式布局(左右固宽,中间自适应)的五种方法

    代码: <!-- 1 float --> <h3 class="block">第一种方法-float</h3> <div class=&q ...

  2. 手工删除crfclust.bdb文件

    环境:RHEL 6.5 + Oracle 11.2.0.4 RAC 现象:巡检发现自己的测试环境节点2的空间使用率过高,进一步查询,发现大文件是GI目录下crfclust.bdb文件. crfclus ...

  3. c语言中的文件格式化读写函数fscanf和fprintf函数

    很多时候我们需要写入数据到文件中时都觉得很困扰,因为格式乱七八槽的,可读性太差了,于是我们就想有没有什么函数可以格式化的从文件中输入和输出呢,还真有.下面我将讲解一下fscanf和fprintf的强大 ...

  4. java常见加密方式介绍

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt260 本篇内容简要介绍BASE64.MD5.SHA.HMAC几种加密算法.  ...

  5. [转]RMI方式Ehcache集群的源码分析

    RMI方式Ehcache集群的源码分析   Ehcache不仅支持基本的内存缓存,还支持多种方式将本地内存中的缓存同步到其他使用Ehcache的服务器中,形成集群.如下图所示:   Ehcache支持 ...

  6. bootstrap 基础(二)

    1 栅格系统偏移 栅格系统的偏移只能向右:col-xs-offset-x. <!DOCTYPE html> <html lang="en"> <hea ...

  7. hdu 2066 最短路水题

    题意:给出多个可选择的起始点和终点,求最短路 思路:执行起始点次的spfa即可 代码: #include<iostream> #include<cstdio> #include ...

  8. JTemplates 的使用

    注意事项:一定要放在Jquery的页面加载完成事件内  : $(function{}); <script src="~/Js/jquery-2.1.0.js">< ...

  9. 前端AES的加密和解密

    在工作的过程中,经常要对一些数据做一些加密,当然有复杂的加密和简单的加密,也有对称加密等等.总之加密的方式有很多.今天在这里,我只是简单的分享一个我最近遇到的加密方式-AES.这个也是后端工程师用的, ...

  10. 2017春季 JMU 1414软工助教 链接汇总

    助教自我介绍 学生博客链接和coding链接 [1414软工助教]团队博客汇总 助教总结 评分 个人作业1:四则运算控制台 结对项目1:GUI 个人作业2:案例分析 结对项目2:单元测试 团队作业1: ...