Java Spring各种依赖注入注解的区别
Spring常用的三种注入方式

Spring常⽤的三种注⼊⽅式Spring通过DI(依赖注⼊)实现IOC(控制反转),常⽤的注⼊⽅式主要有三种:构造⽅法注⼊,setter注⼊,基于注解的注⼊。
构造⽅法注⼊先简单看⼀下测试项⽬的结构,⽤maven构建的,四个包:entity:存储实体,⾥⾯只有⼀个User类dao:数据访问,⼀个接⼝,两个实现类service:服务层,⼀个接⼝,⼀个实现类,实现类依赖于IUserDaotest:测试包在spring的配置⽂件中注册UserService,将UserDaoJdbc通过constructor-arg标签注⼊到UserService的某个有参数的构造⽅法<!-- 注册userService --><bean id="userService" class="erService"><constructor-arg ref="userDaoJdbc"></constructor-arg></bean><!-- 注册jdbc实现的dao --><bean id="userDaoJdbc" class="erDaoJdbc"></bean>如果只有⼀个有参数的构造⽅法并且参数类型与注⼊的bean的类型匹配,那就会注⼊到该构造⽅法中。
public class UserService implements IUserService {private IUserDao userDao;public UserService(IUserDao userDao) {erDao = userDao;}public void loginUser() {userDao.loginUser();}}@Testpublic void testDI() {ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");// 获取bean对象UserService userService = ac.getBean(UserService.class, "userService");// 模拟⽤户登录userService.loginUser();}测试打印结果:jdbc-登录成功注:模拟⽤户登录的loginUser⽅法其实只是打印了⼀条输出语句,jdbc实现的类输出的是:jdbc-登录成功,mybatis实现的类输出的是:mybatis-登录成功。
Spring的四个基本注解ann...

Spring的四个基本注解ann...SpringMVC的四个基本注解annotation(控制层,业务层,持久层) -- @Component、@Repository @Service、@Controller SpringMVC中四个基本注解:@Component、@Repository @Service、@Controller看字面含义,很容易却别出其中三个:@Controller控制层,就是我们的action层@Service 业务逻辑层,就是我们的service或者manager 层@Repository持久层,就是我们常说的DAO层而@Component (字面意思就是组件),它在你确定不了事哪一个层的时候使用。
其实,这四个注解的效果都是一样的,Spring都会把它们当做需要注入的Bean加载在上下文中;但是在项目中,却建议你严格按照除Componen的其余三个注解的含义使用在项目中。
这对分层结构的web架构很有好处!!这里讲的是SpringMVC中这四个注解的作用,其实Srping中这四个注解的作用和SpringMVC一样.示例:1. 控制层@Controller // 注释为controller@RequestMapping("/login")public class LoginAction {@Autowired@Qualifier("userService") //注释指定注入 Beanprivate IUserService userService;。
其他略。
}2. 业务逻辑层@Service("userService")public class UserServiceImpl implements IUserService {@Autowired@Qualifier("userDao")private IUserDao userDao;。
Spring注解@Componen、@Repository@Service、@Controller区别

Spring 2.5 中除了提供@Component 注释外,还定义了几个拥有特殊语义的注释,它们分别是:@Repository、@Service 和@Controller。
在目前的Spring 版本中,这3 个注释和@Component 是等效的,但是从注释类的命名上,很容易看出这 3 个注释分别和持久层、业务层和控制层(Web 层)相对应。
虽然目前这 3 个注释和@Component 相比没有什么新意,但Spring 将在以后的版本中为它们添加特殊的功能。
所以,如果Web 应用程序采用了经典的三层分层结构的话,最好在持久层、业务层和控制层分别采用@Repository、@Service 和@Controller 对分层中的类进行注释,而用@Component 对那些比较中立的类进行注释。
在一个稍大的项目中,通常会有上百个组件,如果这些组件采用xml的bean定义来配置,显然会增加配置文件的体积,查找以及维护起来也不太方便。
Spring2.5为我们引入了组件自动扫描机制,他可以在类路径底下寻找标注了@Component,@Service,@Controller,@Repository注解的类,并把这些类纳入进spring容器中管理。
它的作用和在xml文件中使用bean节点配置组件时一样的。
要使用自动扫描机制,我们需要打开以下配置信息:Java代码1. <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="/schema/beans" xmlns:xsi="/2001/XMLSchema-instance"xmlns:context="/schema/context"xsi:schemaLocation="/schema/beans/schema/beans/spring-beans-2.5.xsd/schema/context/schema/context/spring-context-2.5.xsd"2. >3.4. <context:component-scan base-package=”com.eric.spring”>5. </beans>6. 其中base-package为需要扫描的包(含所有子包)@Service用于标注业务层组件,@Controller用于标注控制层组件(如struts中的action),@Repository用于标注数据访问组件,即DAO组件,而@Component 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
spring4——IOC之基于注解的依赖注入(DI)

spring4——IOC之基于注解的依赖注⼊(DI)spring容器对于Bean的创建和对象属性的依赖注⼊提供了注解的⽀持,让我们在开发中能够更加便捷的实现对象的创建和对象属性的依赖注⼊。
⼀,对于Bean的创建spring容器提供了以下四个注解的⽀持:1、@Component2、@Repository dao层实现类的注解3、@Service service层实现类的注解4、@Controller controller层实现类的注解以上四个注解在普通使⽤中是等效的,但在web项⽬中为了区分三层架构中不同层之间Bean的创建,为了避免注解使⽤的混乱,使⽤后三个注解进⾏区分。
⼆,对于Bean属性的依赖注⼊分为两类,⼀类是对于属性是String类型或者基本数据类型Spring容器提供了@Value这个注解,另⼀类是对于属性是对象的提供了@Autowired和@Resource这两个注解。
其中,@Autowired这个注解是spring框架⾃带的注解,⽽@Resource(javax.annotation.Resource)这个注解是javax扩展包中注解规范的⼀种,⽽spring对这⼀注解提供了⽀持。
下⾯我们通过实验来说明注解对于bean创建和bean属性依赖注⼊的实现。
⾸先要在配置⽂件中配置注解扫描的驱动。
<context:annotation-config/><context:component-scan base-package="com.opensource"/>这⾥提⼀句,如果配置了注解扫描包的范围,也就是第⼆⾏,那么<context:annotation-config/>可以不⽤配置,因为配置扫描包的范围后,注解的驱动也就有了。
实验⼀,bean的创建,因为spring容器对于bean创建的四个注解是等效,这⾥我们使⽤@Component这个注解Student类:@Componentpublic class Student {public Student(){System.out.println("spring容器调⽤Student类的⽆参构造器");}测试类:public class MyTest {public static void main(String[] args) {ApplicationContext ac = new ClassPathXmlApplicationContext("spring-bean.xml");}}实验结果:实验⼆:bean属性为String类型及基本数据类型的的依赖注⼊student类:@Component(value = "student")public class Student {@Value("张三")private String name;@Value("23")private int age;public String getName() {return name;}public int getAge() {return age;}}在这⾥ @Component(value = "student") value指定的是bean的id,另外对于注解⽅式实现的依赖注⼊,bean的属性⽆需再提供setter⽅法。
Spring注解@component、@service、@Autowired等作用与区别

Spring注解@component、@service、@Autowired等作⽤与区别1、@Service⽤于标注业务层组件2、@Controller⽤于标注控制层组件(如struts中的action)3、@Repository⽤于标注数据访问组件,即DAO组件.4、@Component泛指组件,当组件不好归类的时候,我们可以使⽤这个注解进⾏标注。
5、@Autowired与@Resource的区别: @Autowired由Spring提供,只按照byType注⼊,默认情况下必须要求依赖对象存在,如果要允许null值,可以设置它的required属性为false。
如果想使⽤名称装配可以结合@Qualifier注解进⾏使⽤。
public class UserService {@Autowired@Qualifier(name="userDao1")private UserDao userDao;} @Resource由J2EE提供,默认按照byName⾃动注⼊,Spring将@Resource注解的name属性解析为bean的名字,type属性则解析为bean的类型。
所以如果使⽤name属性,则使⽤byName的⾃动注⼊策略,⽽使⽤type属性则使⽤byType⾃动注⼊策略。
①如果同时指定了name和type,则从Spring上下⽂中找到唯⼀匹配的bean进⾏装配,找不到则抛出异常。
②如果指定了name,则从上下⽂中查找名称(id)匹配的bean进⾏装配,找不到则抛出异常。
③如果指定了type,则从上下⽂中找到类似匹配的唯⼀bean进⾏装配,找不到或是找到多个,都会抛出异常。
④如果既没有指定name,⼜没有指定type,则⾃动按照byName⽅式进⾏装配;如果没有匹配,则回退为⼀个原始类型进⾏匹配,如果匹配则⾃动装配。
总结:@Resource的作⽤相当于@Autowired,只不过@Autowired按byType⾃动注⼊。
spring四种依赖注入方式

s p r i n g四种依赖注入方式The document was finally revised on 2021博客分类:•??平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new 一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。
依赖注入的另一种说法是“控制反转”,通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做。
spring有多种依赖注入的形式,下面仅介绍spring通过xml进行IOC配置的方式:•Set注入这是最简单的注入方式,假设有一个SpringAction,类中需要实例化一个SpringDao对象,那么就可以定义一个private的SpringDao成员变量,然后创建SpringDao的set方法(这是ioc的注入入口):Java代码1.package?2.publicclassSpringAction{.>,这样其实是spring将SpringDaoImpl对象实例化并且调用SpringAction 的setSpringDao方法将SpringDao注入:Java代码1.<!--配置bean,配置后该类由spring管理-->?2.<beanname="springAction"class="">?3.4.<!--(1)依赖注入,配置当前类中相应的属性-->5.<propertyname="springDao"6.ref="springDao"></property>?7.8.</bean>9.<beanname="springDao"class=""></bean>?10.11.•构造器注入这种方式的注入是指带有参数的构造函数注入,看下面的例子,我创建了两个成员变量SpringDao和User,但是并未设置对象的set方法,所以就不能支持第一种注入方式,这里的注入方式是在SpringAction 的构造函数中注入,也就是说在创建SpringAction对象时要将SpringDao和User两个参数值传进来:Java代码1.publicclassSpringAction{态方法()"来获取对象,而是依然通过spring注入的形式获取:Java代码1.package?2.3.import?4.import?5.import?6.7.publicclassDaoFactory{1.."class="..."scope="prototype">。
【转】Spring学习笔记1—依赖注入(构造器注入、set注入和注解注入)

【转】Spring学习笔记1—依赖注⼊(构造器注⼊、set注⼊和注解注⼊)什么是依赖注⼊在以前的java开发中,某个类中需要依赖其它类的⽅法时,通常是new⼀个依赖类再调⽤类实例的⽅法,这种⽅法耦合度太⾼并且不容易测试,spring提出了依赖注⼊的思想,即依赖类不由程序员实例化,⽽是通过spring容器帮我们new指定实例并且将实例注⼊到需要该对象的类中。
依赖注⼊的⽅式依赖注⼊有3种⽅式:构造器注⼊、set注⼊和注解注⼊。
1.构造器注⼊构造器注⼊保证⼀些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使⽤。
使⽤⽅式:1. 在类中,不⽤为属性设置setter⽅法,但是需要⽣成该类带参的构造⽅法。
2. 在配置⽂件中配置该类的bean,并配置构造器,在配置构造器中⽤到了<constructor-arg>节点,该节点有四个属性index:指定注⼊属性的顺序索引,从0开始;type:指该属性所对应的类型;ref:引⽤的依赖对象;value:当注⼊的不是依赖对象,⽽是基本数据类型时,就⽤value;例⼦1:public class SpringAction {//注⼊对象springDaoprivate SpringDao springDao;private User user;public SpringAction(SpringDao springDao,User user){this.springDao = springDao;er = user;System.out.println("构造⽅法调⽤springDao和user");}public void save(){user.setName("卡卡");springDao.save(user);}}<bean name="springAction" class="com.bless.springdemo.action.SpringAction"><!--(2)创建构造器注⼊,如果主类有带参的构造⽅法则需添加此配置--><constructor-arg index="0" ref="springDao"></constructor-arg><constructor-arg index="1" ref="user"></constructor-arg></bean><bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean><bean name="user" class="er"></bean>其中index属性表⽰注⼊的bean在构造⽅法中的参数顺序。
论述spring依赖注入中注解分类、作用及应用方式

论述spring依赖注入中注解分类、作用及应用方式spring依赖注入(DI)是把实例对象放在spring容器中运用注解注入进行实例依赖关系的维护,通常可分为以下几类:一、 Spring注解:1、 @Resource:该注解直接用欧文名字,如 applicationContext.xml 里定义的 bean 的名字作为注解的 value 属性,通过名字装配bean。
2、 @Autowired:该注解根据类型装配bean,如果项目中有多个实现类型的bean 那么需要标注 @Qualifier("beanName") 来指定注入bean为哪一个。
3、 @Value:该注解通过表达式来设置属性值,可以是一个字符串、某个bean 的属性值、某个配置文件的值等,例如@Value("#{systemProperties['']}"),表示从systemProperties取出为属性值4、 @PostConstruct:该注解标注的方法会在bean初始化的时候执行,也可以在配置文件中配置 init-method="methodName",当容器装配完成 bean 的时候会调用methodName 对应的方法5、 @PreDestroy:该注解标注的方法会在bean销毁的时候执行,也可以在配置文件中配置 destroy-method="methodName",当容器销毁 bean 的时候会调用methodName 对应的方法二、 JavaEE注解:1、 @javax.annotation.Resource :该注解可以直接通过它的 property name 属性来指定注入bean 名字2、 @javax.inject.Inject:该注解是JavaEE6 中出现的,和 @Autowired 一样可以根据类型装配bean三、其他的注解:1、 @Repository:该注解用来标注 Dao 层的组件,表明该组件是一个数据访问层的实现2、 @Service:该注解用来标注 Service 层的组件,表明是业务类组件3、 @Controller:该注解用来标注 controller 层的组件,进行请求处理这些注解有一些作用是相同的,比如都可以被spring容器所扫描到,但他们各有特殊用途,且使用方式也各有不同,以上便是spring依赖注入中注解分类、作用及应用方式的详细介绍。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Spring对于Bean的依赖注入,支持多种注解方式:
直观上看起来,@Autowired是Spring提供的注解,其他几个都是JDK本身内建的注解,Spring 对这些注解也进行了支持。
但是使用起来这三者到底有什么区别呢?笔者经过方法的测试,发现一些有意思的特性。
区别总结如下:
一、@Autowired有个required属性,可以配置为false,这种情况下如果没有找到对应的bean 是不会抛异常的。
@Inject和@Resource没有提供对应的配置,所以必须找到否则会抛异常。
二、@Autowired和@Inject基本是一样的,因为两者都是使用AutowiredAnnotationBeanPostProcessor来处理依赖注入。
但是@Resource是个例外,它使用的是CommonAnnotationBeanPostProcessor来处理依赖注入。
当然,两者都是BeanPostProcessor。
TIPS Qualified name VS Bean name
在Spring设计中,Qualified name并不等同于Bean name,后者必须是唯一的,但是前者类似于tag或者group的作用,对特定的bean进行分类。
可以达到getByTag(group)的效果。
对于XML配置的bean,可以通过id属性指定bean name(如果没有指定,默认使用类名首字母小写),通过标签指定qualifier name:
如果是通过注解方式,那么可以通过@Qualifier注解指定qualifier name,通过@Named或者@Component(@Service,@Repository等)的value值指定bean name:
或者
同样,如果没有指定bean name,那么Spring会默认是用类名首字母小写
(Lamborghini=>lamborghini)。
三、通过Anotation注入依赖的方式在XML注入方式之前进行。
如果对同一个bean的依赖同时使用了两种注入方式,那么XML的优先。
但是不同担心通过Anotation注入的依赖没法注入XML中配置的bean,依赖注入是在bean的注册之后进行的。
四、目前的autowired by type方式(笔者用的是3.2.3.RELEASE版本),Spring的AutowiredAnnotationBeanPostProcessor实现都是有”bug”的,也就是说@Autowired和@Inject 都是有坑的(称之为坑,不称之为bug是因为貌似是故意的。
)。
这是来源于线上的一个bug,也是这边文章的写作原因。
现场如下:
application-context.xml中有如下定义:
其中static-field应用的常量定义在如下类中:
然后如果我们在代码中如下声明依赖:
Guess what,诡异的事情发生了!运行结果如下:
也就是说Map
debug了一下,发现确实是Spring的一个bug。
在DefaultListableBeanFactory的这个方法出问题了:
关键在这一句:Map
debug了一下,发现跟没有指定qualifie name是一样的执行路径。
不是指定了bean name了吗?为什么还是autowired by type呢?仔细查看了一下才发现。
DefaultListableBeanFactory 的doResolveDependency方法对首先对类型做了区别:
如果是Array,Collection或者Map,则根据集合类中元素的类型来进行autowired by type(Map 使用value的类型)。
为什么这么特殊处理呢?原来,Spring是为了达到这样的目的:让你可以一次注入所有符合类型的实现,也就是说可以这样子注入:
如果你的car有多个实现,那么都会注入进来,不会再报
然而,上面的情况如果你用@Resource则不会有这个问题:
正常运行:
当然,你如果不指定@Qualifier(“languageChangesMap”),同时field name不是languageChangesMap,那么还是一样报错的。
而且,@Resource也可以实现上面的List接收所有实现:
运行的妥妥的:
这是因为@Resource注解使用的是CommonAnnotationBeanPostProcessor处理器,跟AutowiredAnnotationBeanPostProcessor不是同一个作者[/偷笑]。
这里就不分析了,感兴趣的同学可以自己看代码研究一下。
最终结论如下:
1、@Autowired和@Inject
2、@Resource
测试工程保存在GitHub上,是标准的maven工程,感兴趣的同学可以clone到本地运行测试一下。
补充
有同事指出Spring官方文档上有这么一句话跟我的结有点冲突:
也就是说@Autowired即使加了@Qualifier注解,其实也是autowired by type。
@Qualifier只是一个限定词,过滤条件而已。
重新跟进了一下代码,发现确实是这样子的。
Spring设计的这个@Qualifier name 并不等同于bean name。
他有点类似于一个tag。
不过如果这个tag 是唯一的化,那么其实效果上等同于bean name。
实现上,Spring是先getByType,得到list candicates,然后再根据qualifier name进行过滤。
再定义一个兰博基尼,这里使用@Qualifier指定:
再定义一个劳斯莱斯,这里故意用@Named指定:
测试一下注入定义的豪华车:
运行结果如下:
补充:Autowiring modes
Spring支持四种autowire模式,当使用XML配置方式时,你可以通过autowire属性指定。
如果使用@Autowired、@Inject或者@Resource注解的时候,则稍微复杂一些,会有一个失败退化过程,并且引入了Qualifier。
不过基本原理是一样。