虽然Spring管理这我们的Bean很方便,但是,我们需要使用xml配置大量的Bean信息,告诉Spring我们要干嘛,这还是挺烦的,毕竟当我们的Bean随之增多的话,xml的各种配置会让人很头疼。
所以我们需要一种东西来解决这个问题,这就是——注解,这次我们使用注解来将我们学过的所有东西重新做过一遍。
注解是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
这里有几篇博文可供大家参考,其实了解注解可以让自己使用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
这里的依赖于上篇博客的并没有什么不同之处,依赖主要如下:
- <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>
添加了相关的依赖后我们现在就要对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加载了
,这是有关数据库的相关配置,之前是直接在配置文件写入,现在进行了提取,然后利用了context进行加载。 db.properties文件也是置于classpath下,具体内容是
- db.properties
- jdbc.driver=com.mysql.jdbc.Driver
- jdbc.url=jdbc:mysql://localhost:3306/spring_demo_1
- jdbc.username=root
- jdbc.password=root
好,经过上面的折腾之后就可使用注解开发我们程序了,接下来进入主题。
现在有一个场景,就是一个人拥有一只小狗叫旺财,如果参考之前的博客我的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 + '\'' +
- '}';
- }
- }
有了上面的准备工作之后,我们可以对我们的代码进行简单的测试了,我们现在不使用
来加载我们的Bean了,而是使用Spring test,同样的利用注解可以剩下很多事情,代码主要如下:
- ClassPathXmlApplicationContext
- //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='公'}}
现在我们的
没有时间去看管我们的狗狗
- 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并没有什么结果上的不同,成功。
好,通过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事务配置就先是这么多
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下载
来源: http://www.cnblogs.com/lger/p/7622792.html