虽然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. Mysql数据库索引

    今天,我们来讲讲Mysql数据库的索引的一些东西,想必大家都知道索引能干吗?必然是查找数据表的时候,查找的速度快啊,尤其是那些几百万行的数据库,不建立索引,你是想考验用户的耐心吗?Mysql有多种存储 ...

  2. login shell与non-login shell的区别

    Bash应该是我们每天日常工作接触最多的东西了,就像我们最忠实的朋友,我们有必要了解一下这位朋友的“习性”. Bash有几种不同的运行模式,login shell与non-login shell,in ...

  3. MongoDb 入门教程

    MongoDb 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 它是可扩展的高性能数据存储解决方案,经常被用于非关系型数据的存储,能存储海量的数据. 常 ...

  4. 哪有Python视频百度云链接?

    说到Python视频哪个好,小编在这里不好下结论.毕竟孰好孰坏,只有合适的才是最好的.就像买鞋子,一双鞋子好不好,只有合脚才是真的好.不过,这里有些个人认为通俗易懂的Python视频可以分享给大家. ...

  5. 谈谈.NET,Java,php

    开通博客后,一直都是转点别的朋友写的有意思的博文,今天我来写我在博客园的第一篇文章,说的不对的地方请你指正.希望本文能为一些准备学习编程的朋友有一点帮助. 开发桌面程序一直都是c语言,c++的天下,因 ...

  6. Stylus-NodeJS下构建更富表现力/动态/健壮的CSS

    --------------------------本文来自张鑫旭大神博客------------------------------ 一.为什么我会讲Stylus,而不是SASS和LESS? SAS ...

  7. CSS3动画效果之transition

    CSS3中有两种方式实现动画,transition和animation+@keyframe. 两者的作用机制不一样:transition定义在可能要进行动画的元素上,对某些CSS属性进行监听,一旦CS ...

  8. iOS ipa包瘦身------删除无用图片资源

         随着客户端业务的增多和业务的更新,App包大小越来越大,优化包大小是迫在眉睫,客户端需要优化的地方也有很多,本期主要讲如何查找无用图片并且删除无用图片的方法.      方案1:(暴力方法) ...

  9. 201521123106 《Java程序设计》第5周学习总结

    1. 本章学习总结 2. 书面作业 Q1. 代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误.并分析输出结果. 答 ...

  10. 201521123066 《Java程序设计》第十四周学习总结

    1. 本周学习总结 2. 书面作业 1. MySQL数据库基本操作 建立数据库,将自己的姓名.学号作为一条记录插入.(截图,需出现自己的学号.姓名) 在自己建立的数据库上执行常见SQL语句(截图) - ...