基于注解的DI
通过spring的注解完成对java对象的创建,属性的赋值,代替xml文件
ioc能够实现业务和对象之间的解耦合,例如service和dao对象之间的解耦合
常用注解:
- @Component、创建对象
- @Respotory、创建dao对象,用来访问数据库
- @Service、创建Service对象,处理业务逻辑,可以有事务的功能
- @Controller、创建控制器对象,接收请求,显示处理结果
- @Value、简单类型的属性赋值
- @Autowired、spring框架中引用类型赋值的注解,支持byName、byType,默认byType
- @Resource、jdk中的注解,使用自动注入给引用数据类型赋值,支持byName、byType,默认byName
一、使用注解的步骤
- 加入maven的依赖 spring-context ,在你加入spring-context的同时, 间接加入spring-aop的依赖,使用注解必须使用spring-aop依赖
- 在类中加入spring的注解(多个不同功能的注解)
- 在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
<context:component-scan base-package="包名"/>
- 使用注解创建对象, 创建容器ApplicationContext
首先还是创建一个新的项目,在pom.xml文件中加入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
二、@Component
首先创建学生类
package com.md.b1;
import org.springframework.stereotype.Component;
/**
* @author MD
* @create 2020-08-08 15:51
* @Component: 创建对象的, 等同于<bean>的功能
* 属性:value 就是对象的名称,也就是bean的id值,
* value的值是唯一的,创建的对象在整个spring容器中就一个
* 位置:在类的上面
*
* @Component(value = "myStudent")等同于
* <bean id="myStudent" class="com.bjpowernode.ba01.Student" />
*/
//@Component(value = "myStudent")
// 省略value,常用
@Component("myStudent")
// 不指定对象的名称,由spring默认提供:为类名首字母小写(student)
//@Component
public class Student {
private String name;
private Integer age;
public Student() {
System.out.println("我是Student的无参构造方法");
}
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
然后在spring的配置文件中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: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/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!--声明组件扫描器,组件就是java对象
base-package:指定注解在你项目中的包名
component-scan工作方式:spring会扫描遍历base-package指定的包,
找包中以及子包中的所有的类,并找到类中的注解,
按照注解的功能创建对象,或者给属性赋值
-->
<context:component-scan base-package="com.md.b1"/>
</beans>
测试:
package com.md;
import com.md.b1.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author MD
* @create 2020-08-08 16:05
*/
public class MyTest01 {
@Test
public void test01(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器中获取对象
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
}
}
注意一:指定多个包的三种方式
<!--第一种方式:使用多次组件扫描器,指定不同的包-->
<context:component-scan base-package="com.md.b1"/>
<context:component-scan base-package="com.md.b2"/>
<!--第二种方式:使用分隔符(;或,)分隔多个包名-->
<context:component-scan base-package="com.md.b1;com.md.b2" />
<!--第三种方式:指定父包-->
<context:component-scan base-package="com.md" />
重点:
注意二:spring中和@Component功能一致,创建对象的注解还有
- @Repository(用在持久层类的上面) : 放在dao的实现类上面,表示创建dao对象,dao对象是能访问数据库的
- @Service(用在业务层类的上面):放在service的实现类上面,创建service对象,service对象是做业务处理,可以有事务等功能的
- @Controller(用在控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,控制器对象,能够接受用户提交的参数,显示请求的处理结果。
以上三个注解的使用语法和@Component一样的。 都能创建对象,但是这三个注解还有额外的功能
@Repository,@Service,@Controller是给项目的对象分层的
某个类使用上面的三个注解都不合适的时候使用@Component
问题:创建对象的注解有几个,为什么有多个?
三、@Value
简单类型属性注入,需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值
使用该注解完成属性注入时,类中无需 setter。当然,若属性有 setter,则也可将其加到 setter 上
如下:
package com.md.b2;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author MD
* @create 2020-08-08 15:51
*/
@Component("myStudent")
public class Student {
/**
* @Value: 简单类型的属性赋值
* 属性: value 是String类型的,表示简单类型的属性值
* 位置: 1.在属性定义的上面,无需set方法,推荐使用。
* 2.在set方法的上面
*/
// @Value(value = "比比东")
@Value("比比东")
private String name;
// @Value(value = "18")
@Value("22")
private Integer age;
public Student() {
System.out.println("我是Student的无参构造方法");
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
然后在spring的配置文件中applicationContext.xml加入组件扫描器
<context:component-scan base-package="com.md.b2"/>
测试
@Test
public void test01(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器中获取对象
Student student = (Student) ac.getBean("myStudent");
System.out.println(student);
//我是Student的无参构造方法
//Student{name='比比东', age=22}
}
四、@Autowired
byType自动注入
@Autowired:spring框架提供的注解,实现引用类型的赋值
需要在引用属性上使用注解@Autowired,该注解默认使用按类型自动装配Bean的方式(byType)
package com.md.b3;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author MD
* @create 2020-08-08 16:39
*/
@Component("student")
public class Student {
@Value("比比东")
private String name;
@Value("20")
private Integer age;
/**
* 引用数据类型
* @Autowired:spring框架提供的注解,实现引用类型的赋值
* spring中通过注解给引用数据类型赋值的原理是使用自动注入,支持byName,byType
* 默认使用的byType默认注入
*
* 使用:在属性定义的上面,无需set方法,推荐
* 在set方法的上面
*/
// 使用注解在School类里定义对象名称,以及属性值 或 使用bean的方式创建对象以及通过set方法给属性赋值
@Autowired
private School school;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
School类
package com.md.b3;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @author MD
* @create 2020-08-08 16:40
*/
@Component("mySchool")
public class School {
@Value("交大")
private String name;
@Value("上海")
private String address;
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
}
然后在spring的配置文件中applicationContext.xml加入组件扫描器
<context:component-scan base-package="com.md.b3"/>
测试和上面一样,就不写了,除了使用注解还可以使用xml的方式
这样就是可以的,
<bean id="school" class="com.md.b3.School">
<property name="name" value="上海交通大学"/>
<property name="address" value="上海"/>
</bean>
五、@Qualifier
byName自动注入
由于@Autowired 默认使用的是byType,为了使用byName方式,
需要在引用属性上联合使用注解@Autowired 与@Qualifier
@Qualifier 的 value 属性用于指定要匹配的 Bean 的 id 值,
使用byName方式
1. 属性的上面加入@Autowired注解
2. 属性的上面加@Qualifier(value="bean的id")注解,表示使用指定名称的bean完成赋值
也就是使用这个对象来完成赋值
School类
@Component("school")
public class School {
@Value("厦门大学")
private String name;
@Value("厦门")
private String address;
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
Student类
@Component("student")
public class Student {
@Value("比比东")
private String name;
@Value("20")
private Integer age;
// 在School类里通过注解直接对象名为school
@Autowired
@Qualifier("school")
private School school;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
属性:required ,是一个boolean类型的,默认true
- required=true:表示引用类型赋值失败,程序报错,并终止执行。推荐使用
- required=false:引用类型如果赋值失败, 程序正常执行,引用类型是null
例如:还是在上面的程序上
使用的是byName的方式,而此时失误bean的id写错了
- 若使用默认值,则结果或报错
- 若按照下面写的执行,则不会报错,但数据为空
@Component("student")
public class Student {
@Value("比比东")
private String name;
@Value("20")
private Integer age;
// 在School类里通过注解直接对象名为school
@Autowired(required = false)
@Qualifier("schoo")
private School school;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
六、@Resource
spring提供了对jdk中@Resource注解的支持。
@Resource注解既可以按名称匹配Bean,也可以按类型匹配 Bean。 默认是按名称注入(byName)
使用该注解,要求 JDK 必须是 6 及以上版本,@Resource 可在属性上,也可在 set 方法上
还是School类中
@Component("school")
public class School {
@Value("浙江大学")
private String name;
@Value("浙江")
private String address;
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
}
此时Student类
@Component("student")
public class Student {
@Value("比比东")
private String name;
@Value("20")
private Integer age;
/**
* 引用类型
* @Resource: 来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值
* 使用的也是自动注入原理,支持byName, byType .默认是byName
* 位置: 1.在属性定义的上面,无需set方法,推荐使用。
* 2.在set方法的上面
*/
//默认是byName: 先使用byName自动注入,如果byName赋值失败,再使用byType
//@Resource
// 若只使用byName方式,需要增加一个属性 name,name的值就是bean的id(对象名称)
@Resource(name = "school")
private School school;
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", school=" + school +
'}';
}
}
在spring的配置文件中applicationContext.xml加入组件扫描器
<context:component-scan base-package="com.md.b6"/>
测试:
@Test
public void test01(){
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器中获取对象
Student student = (Student) ac.getBean("student");
System.out.println(student);
// Student{name='比比东', age=20, school=School{name='浙江大学', address='浙江'}}
}
七、XML和注解对比
注解优点是:方便、直观、高效(代码少,没有配置文件的书写那么复杂)
缺点:以硬编码的方式写入到 Java 代码中,修改是需要重新编译代码的
适合于不是经常修改的
XML 方式优点是:配置和代码是分离的、在 xml 中做修改,无需编译代码,只需重启服务器即可将新的配置加载
缺点:编写麻烦,效率低,大型项目过于复杂
基于注解的DI的更多相关文章
- SSM-Spring-07:Spring基于注解的di注入
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 注解: 说起注解,哇哦,每个人都或多或少的用到过 像什么@Overried,@Test,@Param等等之前就 ...
- 基于注解的DI(DI:Dependency Injection 依赖注入)
注解方式xml里面就不需要注册bean了. 构建注解需要 1.导入spring-aop-4.2.1.RELEASE.jar 包 2.需要更换配置文件头,即添加相应的约束. 现在的Student类就要 ...
- Spring框架第四篇之基于注解的DI注入
一.说明 与@Component注解功能相同,但意义不同的注解还有三个: 1)@Repository:注解在Dao实现类上 2)@Service:注解在Service实现类上 3)@Controlle ...
- Spring_Spring与IoC_基于注解的DI
一.基本注解的使用 (1)导入AOP的Jar包 (2) 与set()无关 二.组件扫描器的base-package 三.@Component相关注解 四.@Scope 五.域属性的注入 (1)byTy ...
- Spring 02多种注入方式和注解实现DI
一.Bean作用域 spring容器创建的时候,会将所有配置的bean对象创建出来,默认bean都是单例的.代码通过getBean()方法从容器获取指定的bean实例,容器首先会调用Bean类的无参构 ...
- Spring多种注入方式及注解实现DI
一.Bean作用域 spring容器创建的时候,会将所有配置的bean对象创建出来,默认bean都是单例的.代码通过getBean()方法从容器获取指定的bean实例,容器首先会调用Bean类的无参构 ...
- Spring4笔记5--基于注解的DI(依赖注入)
基于注解的DI(依赖注入): 对于 DI 使用注解,将不再需要在 Spring 配置文件中声明 Bean 实例.只需要在 Spring 配置文件中配置组件扫描器,用于在指定的基本包中扫描注解. < ...
- spring(读取外部数据库配置信息、基于注解管理bean、DI)
###解析外部配置文件在resources文件夹下,新建db.properties(和数据库连接相关的信息) driverClassName=com.mysql.jdbc.Driverurl=jdbc ...
- Spring IOC之基于注解的容器配置
Spring配置中注解比XML更好吗?基于注解的配置的介绍提出的问题是否这种途径比XML更好.简单来说就是视情况而定. 长一点的答案是每一种方法都有自己的长处也不足,而且这个通常取决于开发者决定哪一种 ...
随机推荐
- Python Ethical Hacking - BACKDOORS(8)
Cross-platform hacking All programs we wrote are pure python programs They do not rely on OS-specifi ...
- P4017 最大食物链计数(洛谷)
老师开始帮我们查漏补缺啦!我们的老师这两天给了我们一些我们没怎么学的函数和算法,比如STL的函数和拓扑排序之类的,这个题就是讲拓扑排序的. 先看题板: 题目背景 你知道食物链吗?Delia 生物考试的 ...
- T2 监考老师 题解
第二题,他并不是多难的算法.甚至连搜索都不用,他的题目要求和数据断定了他第二题的地位. 在一个大试场里,有 n 行 m 列的考生,小王和众多同学正在考试,这时,有一部分考生 作弊,当然,监考老师能发现 ...
- 机器学习 | SVD矩阵分解算法,对矩阵做拆分,然后呢?
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题第28篇文章,我们来聊聊SVD算法. SVD的英文全称是Singular Value Decomposition,翻译过来 ...
- Google公布编程语言排名,第一竟然是他?
没想到吧,Python 又拿第一了! 在 Google 公布的编程语言流行指数中,Python 依旧是全球范围内最受欢迎的技术语言! 01 为什么 Python 会这么火? 核心还是因为企业需 ...
- 题解 洛谷 P4492 【[HAOI2018]苹果树】
考虑生成一颗二叉树的过程,加入第一个节点方案数为\(1\),加入第二个节点方案数为\(2\),加入第三个节点方案数为\(3\),发现生成一颗\(n\)个节点的二叉树的方案数为\(n!\). 所以题目中 ...
- Eclipse普通java Project文件路径问题
Eclipse普通java Project文件路径问题 项目的结构如图 读取src里某个包下的文件,代码如下 BufferedReader br=new BufferedReader(new File ...
- [leetcode/lintcode 题解] 谷歌面试题:找出有向图中的弱连通分量
请找出有向图中弱连通分量.图中的每个节点包含 1 个标签和1 个相邻节点列表.(有向图的弱连通分量是任意两点均有有向边相连的极大子图) 将连通分量内的元素升序排列. 在线评测地址:https://ww ...
- [转]十分钟带你理解Kubernetes核心概念
本文将会简单介绍 Kubernetes的核心概念.因为这些定义可以在Kubernetes的文档中找到,所以文章也会避免用大段的枯燥的文字介绍.相反,我们会使用一些图表(其中一些是动画)和示例来解释这些 ...
- Markdown显示测试
这是一个一级标题 文本1 文本2 这是一个二级标题 斜体 粗体 粗斜体 下面是分割线 上面是分割线 删除线 下划线 脚注[1] 这是一个三级标题 无序列表1 内容 无序列表2 内容 无序列表3 有序列 ...