之前我们的bean都配置在XML里,并且通过bean的property标签来指定依赖关系,如果项目很大,那岂不是要配置很多这样的property标签?Spring提供了注解的方式来解决这个问题

@Autowired

在需要注入的bean的setter方法上加这个注解,就不需要指定property标签了,因为Spring会通过byType的方式去寻找对应类型的bean自动的注入,如果找到了多个同类型的bean,就会报异常

package com.bjsxt.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User; public class UserService { private UserDAO userDAO; public void init() {
System.out.println("init");
} public void add(User user) {
userDAO.save(user);
}
public UserDAO getUserDAO() {
return userDAO;
} @Autowired
public void setUserDAO( UserDAO userDAO) {
this.userDAO = userDAO;
} public void destroy() {
System.out.println("destroy");
}
}

加上@AutoWired注解的UserService

package com.bjsxt.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.bjsxt.model.User; //Dependency Injection
//Inverse of Control
public class UserServiceTest { @Test
public void testAdd() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); UserService service = (UserService)ctx.getBean("userService");
service.add(new User()); ctx.destroy(); } }

单元测试

运行,会报错,因为发现了u和u2两个可以注入的bean,去掉一个,运行成功

@Qualifier

针对上面的问题,我们可以使用@Qualifier注解,这个注解是通过byName的方式,也就是可以指定id,这个注解需要加在setter方法的参数的最前面,有一个参数表示依赖的bean的id

package com.bjsxt.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User; public class UserService { private UserDAO userDAO; public void init() {
System.out.println("init");
} public void add(User user) {
userDAO.save(user);
}
public UserDAO getUserDAO() {
return userDAO;
} public void setUserDAO(@Qualifier("u") UserDAO userDAO) {
this.userDAO = userDAO;
} public void destroy() {
System.out.println("destroy");
}
}

加上@Qualifier注解的UserService

这样运行就不会报错了,因为会直接找到id为u的bean注入到UserService的userDAO属性

@Resource

  这个注解遵循JSR-250标准,属于J2EE的注解,所以引入新的包“common-annotation.jar”。同样在setter方法上使用该注解,其他部分同上。注意该注解默认使用的是byName的方式,如果没有指定该注解的name属性值,会默认的寻找以setter方法参数的名称为id的bean,例如本例中setter方法的参数名是“userDAO”,就会在配置文件中寻找id为“userDAO”的bean,如果没有找到,就按照byType的方式,如果又发现了两个符合类型的bean,就报异常

先看一个报错的例子

<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
<bean id="u" class="com.bjsxt.dao.impl.UserDAOImpl">
</bean>
<bean id="u2" class="com.bjsxt.dao.impl.UserDAOImpl">
</bean> <bean id="userService" class="com.bjsxt.service.UserService" > </bean> </beans>

配置文件

package com.bjsxt.service;
import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User; public class UserService { private UserDAO userDAO; public void init() {
System.out.println("init");
} public void add(User user) {
userDAO.save(user);
}
public UserDAO getUserDAO() {
return userDAO;
} @Resource
public void setUserDAO( UserDAO userDAO) {
this.userDAO = userDAO;
} public void destroy() {
System.out.println("destroy");
}
}

使用@Resource注解的UserService

package com.bjsxt.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.bjsxt.model.User; //Dependency Injection
//Inverse of Control
public class UserServiceTest { @Test
public void testAdd() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); UserService service = (UserService)ctx.getBean("userService");
service.add(new User()); ctx.destroy(); } }

单元测试

看到了吧,默认按照byName,本来想找id为“userDAO”的bean,结果配置文件中没有,就转为按照byType的方式,结果找到了两个符合类型的bean,id分别为"u"和“u2”。解决办法是给注解加上name="u"来指定一个想要的bean,或者不加name属性,直接在配置文件中指定一个id为"userDAO"bean

@Component

上面的一些注解尽管已经很方便了,但是配置文件里还是要写很多需要被用来注入的bean标签,有没有办法可以让我们连bean标签都不用写呢,答案是肯定的,使用@Component注解就可以做到,我们首先需要在配置文件中加上一句<context:component-scan base-package="com.bjsxt"/>,这句代码的意思就是说:配置文件里面的bean都不用写了,你直接去com.bjsxt下面所有的包里面去扫描加了@componet注解的类作为需要的bean来注入

<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="com.bjsxt"/> <bean id="userService" class="com.bjsxt.service.UserService" > </bean> </beans>

配置文件

已经不用写被用来注入的bean标签了,在setter方法加了@Resource注解的基础上,我们需要在被用来注入的类上加上@Component注解

package com.bjsxt.dao.impl;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller; import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User; @Component("u")
public class UserDAOImpl implements UserDAO { public void save(User user) {
//Hibernate
//JDBC
//XML
//NetWork
System.out.println("user saved!");
} }

UserDAO的实现类UserDAOImpl

package com.bjsxt.service;
import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component; import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User; /*@Component("userService")*/
public class UserService { private UserDAO userDAO; public void init() {
System.out.println("init");
} public void add(User user) {
userDAO.save(user);
}
public UserDAO getUserDAO() {
return userDAO;
} @Resource(name="u")
public void setUserDAO( UserDAO userDAO) {
this.userDAO = userDAO;
} public void destroy() {
System.out.println("destroy");
}
}

UserService

package com.bjsxt.service;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.bjsxt.model.User; //Dependency Injection
//Inverse of Control
public class UserServiceTest { @Test
public void testAdd() throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); UserService service = (UserService)ctx.getBean("userService");
service.add(new User()); ctx.destroy(); } }

单元测试

@Resource和@Component都可以指定一个name来相互对应,这样就可以准确知道setter方法的参数具体需要那个被用来注入的类了

另外我们发现配置文件中还有一个名为“userService”的bean,因为测试代码中调用了getbean("userservice")这个方法,如果把bean标签去掉就找不到了,会报错,我们可以在该bean对应的类上加上@Component标签,并指定名称"userservice”,这样就可以直接把配置文件中的bean去掉了

<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="com.bjsxt"/> </beans>

修改后的配置文件

package com.bjsxt.service;
import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component; import com.bjsxt.dao.UserDAO;
import com.bjsxt.model.User; @Component("userService")
public class UserService { private UserDAO userDAO; public void init() {
System.out.println("init");
} public void add(User user) {
userDAO.save(user);
}
public UserDAO getUserDAO() {
return userDAO;
} @Resource(name="u")
public void setUserDAO( UserDAO userDAO) {
this.userDAO = userDAO;
} public void destroy() {
System.out.println("destroy");
}
}

加上@Component的UserService

项目组织如图:

注:在spring2.5中,@Component,@Repository,@Controller,@Service的作用是一样的,不过在后续版本中就不一定了

最后,再说三个注解

@Scope:参数可以指定为“singleton”或“prototype”,和之前讲的一样,指定bean的生存范围,直接加在类名上就可以了

@PostConstruct:代表之前bean中的init-method,加在方法上就可以了

@PreDestroy:代表之前bean中destroy-method,加在方法上就可以了

尚学堂Spring视频教程(四):使用Annotation的更多相关文章

  1. 尚学堂Spring视频教程(六):AOP Annotation

    此处省略N个字.... 直接看下面 推荐链接: Spring Aop实例之AspectJ注解配置

  2. 尚学堂Spring视频教程(七):AOP XML

    此处省略N个字.... 直接看下面 推荐链接: Spring Aop实例之xml配置

  3. 尚学堂Spring视频教程(五):Spring AOP

    在第一节中,我们自己模拟了一个Spring,实现一个保存用户的操作,假如现在有一个需求,在保存的时候记录日志,该怎么做呢? 暂且将记录日志操作就简单的变为在保存用户前输出一句话“save start. ...

  4. 尚学堂Spring视频教程(三):Spring Core中的其他特性

    集合装配   如果bean中有一些集合属性,配置文件的配置如下 package com.bjsxt.dao.impl; import java.util.List; import java.util. ...

  5. 尚学堂Spring视频教程(二):Spring控制反转

    用Spring来实现IOC 在上节中我们自定义了一个接口BeanFactory和类ClassPathXmlApplicationContext来模拟Spring,其实它们在Spring中确实是存在的, ...

  6. 尚学堂Spring视频教程(一):模拟Spring

    Spring简单的说就是作为控制反转的容器,看这篇文章前需要先搞懂“控制反转和依赖注入“这个设计模式 我们先来模拟Spring,实现用户添加的功能,新建WEB项目”Spring_0100_Abstra ...

  7. [JAVA教程] 2016年最新spring4框架搭建视频教程 【尚学堂】

    Spring4框架 主讲:邹波 类型:SSH 适合对象:学习完javase.数据库技术.jdbc者 Spring4.0作为一个广泛使用的开源框架,它由Rod Johnson创建.它是为了解决企业应用开 ...

  8. 尚学堂 213_尚学堂_高淇_java300集最全视频教程_反射机制_提高反射效率_操作泛型_操作注解_合并文件.mp4

    在反射的时候如果去掉了安全性检测机制,能够大大的提高反射的执行效率,我们来看下面的代码进行比较 package com.bjsxt.test; import java.lang.reflect.Met ...

  9. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

随机推荐

  1. 解决msi文件在XP上安装未完成(提示安装程序被中断,未能安装app。需要重新启动该安装程序进行重试)的问题。

    如图所示,我利用Visual Studio 2015制作了一个小程序.基于.Net 4.0.用VS的Install扩展,新建Install项目进行打包.打包为.msi文件.该安装文件在已经安装了 .N ...

  2. IOS 网络请求

    技术交流新QQ群:414971585 关于网络请求的重要性我想不用多说了吧.对于移动客户端来说,网络的重要性不言而喻.常见的网络请求有同步GET, 同步POST, 异步GET, 异步POST.今天来看 ...

  3. [SimHash] find the percentage of similarity between two given data

    SimHash algorithm, introduced by Charikarand is patented by Google. Simhash 5 steps: Tokenize, Hash, ...

  4. js前台加密,java后台解密实现

    参考资料: JS前台加密,java后台解密实现

  5. pwnable echo1

    最近忙的好久没有更新了,有空把之前拿来练手的CTF pwn题逐渐整理一下放出来 题目是 linux 64位程序 ,流程很简单,大致思路就是先把一个跳转的机器指令写进name的地址,然后溢出覆盖eip, ...

  6. qsort C++ VS2013 leetcode

    class Solution { private: static int compare(const void * a, const void * b) { return (*(int*)a - *( ...

  7. CSS中的class与id区别及用法

    转自http://www.divcss5.com/rumen/r3.shtml及http://www.jb51.net/css/35927.html 我们平常在用DIV CSS制作Xhtml网页页面时 ...

  8. 观察者(Observer)模式又名发布-订阅(Publish/Subscribe)模式、模型-视图(View)模式、源-收听者(Listener)模式或从属者模式

    观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己. 抽象主题(Subject):它把所有观察者对 ...

  9. 树莓派(Raspberry Pi)日期时间不准的修正方法

    在树莓派上,打date命令可以看到系统的日期时间: 后面的CST表示中国标准时间 小知识: 树莓派没有电池,断电后无法保存时间. 树莓派默认安装了NTP(Network Time Protocol)服 ...

  10. ASP.NET的MVC项目BUG——“所需的防伪表单字段‘__RequestVerificationToken’不存在”

    问题:所需的防伪表单字段‘__RequestVerificationToken’不存在 解决办法: [ValidateAntiForgeryToken]能在[HttpPost]下用 [Validate ...