【JavaWeb_Part08】白娘子你就算淹了这深圳,我他妈也要去玩我的 Spring
来源:互联网 发布:淘宝售后处理时间 编辑:程序博客网 时间:2024/04/30 00:32
开篇
mmp,今天上班又迟到了一个小时。一下雨这鬼路上就堵车,简直了。。好了,不吐槽了,昨天挖的坑,今天是时候填上了。内容可能有点多,肾功能不强大者勿看0.0。
常见的几种注入方式
1. Set 方式注入
set 方式注入是除了注解以外最常用的一种方式,我们昨天所说的就是通过 set 方式注入属性值的,具体实现如下:
在 applicationContext.xml中配置:
<!-- 通过 set 方式注入值--><bean id="user" class="com.student.spring.bean.User"> <property name="name" value="二花"/> <property name="address" value="大森林"/></bean>
在实体类中提供 set 方法
public class User { private String name; private String address; public void setName(String name) { this.name = name; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", address='" + address + '\'' + '}'; }}
测试结果:
注意:
- 必须要提供 set 方法,get 方法可以不提供。
- 通过配置 Spring 就可以实现帮我们创建对象的实例,这说明了什么?说明 Spring 底层是通过反射来帮我们创建对象的实例的,如果不提供 set 方法,Spring 将无法通过反射来获取到 setXXX() 方法来帮我们注入值。
- 提供 toString 方法仅仅只是为了打印结果,并没有其他意图。
2. 通过构造器注入值
在 User 对象中添加如下构造函数:
public class User { private String name; private String address; public User(String name, String address) { this.name = name; this.address = address; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", address='" + address + '\'' + '}'; }}
在applicationContext.xml 文件中做如下配置:
<!-- 通过 构造方法的 方式注入值--><bean id="user" class="com.student.spring.bean.User"> <constructor-arg name="name" value="二花"/> <constructor-arg name="address" value="大森林"/></bean>
测试结果:
结果是正常的,不过通过构造函数注入时,除了可以通过
<constructor-arg name="name" value="小明"/>
这种方式外,还可以通过索引来注入,比如把配置文件更改成如下的方式:
<!-- 通过 构造方法的 方式注入值--><bean id="user" class="com.student.spring.bean.User"> <constructor-arg index="0" value="二花"/> <constructor-arg index="1" value="广东深圳"/> </bean>
结果同上面是一样的。(提示:索引从 0 开始)
注意
这里全部都是用的 value ,还记得昨天的文章中有一个 ref 么?为什么要用 value 而不用 ref 请自行去上一篇文章中弄清楚。
假设 User 对象中有另外一个 对象 “Car”, 这个时候我们应该如何注入?如何注入我们试试就知道了。
新建一个 Car 对象
public class Car { private String cname; private Double cprice; public void setCname(String cname) { this.cname = cname; } public void setCprice(Double cprice) { this.cprice = cprice; }}
在 User 对象里面添加
private Car car;public User(String name, String address, Car car) { this.name = name; this.address = address; this.car = car;}
在配置文件 applicationContext.xml 中做如下配置:
<!-- 通过 set 方式注入值--><bean id="car" class="com.student.spring.bean.Car"> <property name="cname" value="保时捷"/> <property name="cprice" value="2000000"/></bean><!-- 通过 构造方法的索引 方式注入值--><bean id="user" class="com.student.spring.bean.User"> <constructor-arg index="0" value="二花"/> <constructor-arg index="1" value="广东深圳"/> <!-- 引用上面 定义的 car--> <constructor-arg index="2" ref="car"/></bean>
结果
我想,到这里,ref 和 value 的用法你应该了解了。如果还不知道什么区别的话,那你这样记吧。
value 是传值的,ref 是传引用的。
这句话可能不太严谨,但是对初学者来说,还是比较好记住的。
3. 其他的注入方式
注入的方式还有
SpEL 表达式注入通过 P 标签注入通过注解注入(重要)
其中 SpEL 表达式 和 p 标签在开发中基本不会用到,这里就不做讲解了。而注解注入,这个是比较重要的知识点,留在后面去说。注解注入也是我们以后开发中最主流的注入方式。
p 标签的注入方式(了解)
<bean id="car" class="com.student.spring.bean.Car" p:cname="奔驰" p:cprice="125000"/> <!-- 通过 p 标签 方式注入值--><bean id="user" class="com.student.spring.bean.User" p:name="宇文玥" p:address="青山院" p:car-ref="car"/>
注意:通过 p 标签注入,一定要提供 set 方法,否则无法注入。
SpEL 的代码我就不写了,有需要的可以去看一些文档。自己要学会举一反三。
注入几种特殊类型
1. 注入数组类型
<!-- 注入数组--><bean id="sptype" class="com.student.spring.bean.SpType"> <property name="strs"> <list> <value>hello</value> <value>world</value> </list> </property></bean>
SpType.java
public class SpType { private String[] strs; public void setStrs(String[] strs) { this.strs = strs; }}
2. 注入 List
这个套路和注入数组一毛一样,这里就只给出配置文件和截图了。
<bean id="sptype" class="com.student.spring.bean.SpType"> <!-- 注入数组--> <property name="strs"> <list> <value>hello</value> <value>world</value> </list> </property> <!-- 注入集合--> <property name="lists"> <list> <value>小明</value> <value>熊大</value> </list> </property></bean>
3. 注入Map
这个和上面的两者稍有区别。也不废话了,直接上配置文件。
<bean id="sptype" class="com.student.spring.bean.SpType"> <!-- 注入数组--> <property name="strs"> <list> <value>hello</value> <value>world</value> </list> </property> <!-- 注入 list--> <property name="lists"> <list> <value>小明</value> <value>熊大</value> </list> </property> <!-- 注入map:map 是以键值对的形式存在的--> <property name="maps"> <map> <entry key="key1" value="value1"/> <entry key="key2" value="value2"/> <entry key="key3" value="value3"/> </map> </property></bean>
运行截图:
4. 注入 Set
套路和 List 已经数组一样,只不过要注意,Set 没有重复的值。
<!-- 注入 set ,这里给 Set 注入了四个值,实际打印只有三个,去掉了重复的 xixi--><property name="sets"> <set> <value>haha</value> <value>hehe</value> <value>xixi</value> <value>xixi</value> </set></property>
截图:
5. 注入属性文件
<property name="prop"> <props> <prop key="key">隔壁老王</prop> <prop key="key2">隔壁老宋</prop> </props></property>
具体测试我就不测试了,挺简单的,有兴趣自己动手,丰衣足食。
Spring 重要的开发方式之注解开发
啥是注解我也就不解释了,不知道的话,推荐你们去重新温习一下 Java 的基础知识。
1. 注解入门
使用注解开发,能够极大的方便我们的开发,所以这也是我们实际开发中必须掌握的一门技术。要使用注解进行开发,我们需要引入 Spring 框架的另外一个包
spring-aop-4.0.2.jar
此时修改我们的 UserServiceImpl.java,在类的上面添加如下注解
//这行注解的功能就相当于<bean id="userService" class="com.student.spring.service.UserServiceImpl">@Component("userService")public class UserServiceImpl implements UserService { @Override public void save() { System.out.println("service 层使用注解"); }}
如果要使该注解生效,我们需要告诉 Spring 容器我们使用了注解。所以我们还需要在配置文件中加上一句话:(开启注解扫描)
<!--开启注解扫描 base-package 是指扫描哪一个包下面的注解--> <context:component-scan base-package="com.student.spring.service"/>
运行结果:
运行结果和我们在配置文件中配置并无其他区别。通过注解,我们不需要再配置文件中在配置数不清的 bean,大大节省了我们的开发时间,也提升了我们的开发效率。
2. 注解功能讲解
@Component 注解是什么意思呢?
Component 是组件的意思,作用在类上的。在我们的 MVC 开发模式中,WEB 层,Service 层以及 Control 层都可以使用该注解。但是为了满足单一职责原则,从该注解又衍生出三个注解:
@Controller 作用在类上,WEB 层使用@Service 作用在类上,Service 层使用@Repository 作用在类上,Dao 层使用
这三个注解本身就是为了使各个模块的功能更加清晰,虽然你使用 @Component 也没错,但是谁也不能保证 Spring 的团队后面不会对该注解进行改动,所以为了避免以后出现不必要的麻烦,还是使用功能分工明确的那三个注解。
So?我们的上面的例子也可以使用 @Service 注解来代替:
//@Component("userService")@Service("userService")public class UserServiceImpl implements UserService { @Override public void save() { System.out.println("service 层使用注解"); }}
实现的效果完全一样。
3. 使用注解注入属性
上面只是讲了解决了配置文件中 bean 标签的简化配置
<bean id="xxx" class="xxx">
那如果我们要注入引用类型和基本数据类型呢?难道没有吗?错,Spring 当然给我们也提供了注解的方式。看下面的几个注解:
@AutoWired@Qualifier@Value
首先从最下面的注解说起
3.1 如果是要注入普通的数据类型,那么非 Value 注解莫属。
修改 UserServiceImpl.java
@Service("userService")public class UserServiceImpl implements UserService {// @Value("二花") @Value(value = "二花") private String name; @Override public void save() { System.out.println("service 层使用注解:===" + name); }}
注意:
Spring 所提供的注解属性值全部都是 value
在注解只有一个属性的前提下,”value = ” 可省略不写
上面的 @Value(value=”二花”) 和 @Value(“二花”) 是等价的
同理 @Service(“userService”) 同样也和 @Service(value=”userService”) 等价
使用注解后,set 方法可以省略。
3.2 注入引用类型
如果是注入引用类型的话,就要看 @AutoWired 和 @Qualifer 这两个注解了。
@AutoWired //按类型装配@Qualifer //强制使用名称注入
先说 @AutoWired 注解
更改 UserDaoImpl.java,要把 UserDaoImpl 也交给 Spring 去管理,必须要加上注解 @Repository 注解。
@Repository(value = "userDao")public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("dao 层操作数据库去保存用户数据"); }}
再改 UserServiceImpl.java
@Service(value = "userService")public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public void save() { System.out.println("service 层保存用户"); userDao.save(); }}
先不谈 AutoWired 的功能,我们先看结果。
测试结果:
嗯,老铁,没毛病。AutoWired 是自动装配的,它默认是按照类型装配的,如果我们把
//在 UserServiceImpl 中@AutoWiredprivate UserDao userDao1;//在 UserDaoImpl 中@Repository("userDao")
结果和上面一样,这是为什么呢?是因为使用了 AutoWired 注解后,他并不是根据 id 去找,而是根据类型去找的,所以不管你更改成什么名字,ud,xxx 等等,都是可以注入成功的。但是这样是会有一个弊端的,如果一个接口有多个实现类,那么此时使用 AutoWired 进行自动装配肯定会出错。那么如何解决上面的问题呢?
当然有解决办法,我们不乱写名字不就可以了么?那么我们的另外一个注解 @Qualifer,这个注解的意思就是强制使用名称去注入
更改 UserDaoImpl.java 和 UserServiceImpl.java 中的代码
@Repository(value = "xxx")public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("dao 层操作数据库去保存用户数据"); }}
@Service(value = "userService")public class UserServiceImpl implements UserService { @Qualifier(value = "xxx") @Autowired private UserDao userxxx; @Override public void save() { System.out.println("service 层保存用户"); userxxx.save(); }}
测试结果:
这样就达到了我们的目的。一个是按类型,一个强制按名称,这两个注解同时使用,只能得出正确的结果。
3.3 Java 提供的 Resource 注解
如果一个接口有多个实现类,那么我们就跟上面一样,需要同时写两个注解,那么这好像一点也不程序员,不满足我们程序员的风格,能不能再简单一点呢?当然可以,Java 中有一个注解是得到了 Spring 的支持了的,他就是 Resource 注解,这个注解的功能就相当于上面的 AutoWired 注解和 Qualifer 注解同时使用。
这样更改 UserServiceImpl.java
@Service(value = "userService")public class UserServiceImpl implements UserService { @Resource(name = "xxx") private UserDao userxxx; @Override public void save() { System.out.println("service 层保存用户"); userxxx.save(); }}
图片展示的结果已经说明了一切,一切尽在不言中。
bingo!此处应该有掌声。。。(鸦雀无声),好吧,此时无声胜有声也行。(自抱自泣.jpg)
3.4 其他注解
Bean的作用范围注解
1. 注解为@Scope(value=”prototype”),作用在类上。值如下:
2. singleton – 单例,默认值
3. prototype – 多例Bean的生命周期的配置(了解)
注解如下:
1. @PostConstruct – 相当于init-method
2. @PreDestroy – 相当于destroy-method
OK,完美收工。
结尾
一点注解和注入方式就讲了这么多,好啦,下面的东西留到下篇文章吧,毕竟需要消化一下。能力有限,只能写出这样的文章,如果有错误的地方,还烦请给我指出,以免误导他人,同时欢迎留言交流。
- 【JavaWeb_Part08】白娘子你就算淹了这深圳,我他妈也要去玩我的 Spring
- 就算我对你的爱
- 就算你能想到我做任何事情的目的:难道我就错了吗?
- 看了《就算老公一毛钱股份都没拿到 在我心里他依然是最牛逼的创业者》小感
- 如此来说这样的人那就算了吧当我二吧我傻吧其实你妆阻
- 我的娘子(创作中。。)
- 我爱的他,你去哪了?
- 我你他的故事
- 我把你、我、他刻进了光盘!
- 我等待着我的绽放 - 就算再寂寞,也不投向你的怀抱
- 方便你我他
- Monad你我他
- Monad你我他
- 你 我 他
- 我准备去深圳了
- 那些年的你我他
- 李占通他道出了我的心声
- 就算和你没有结局,我还是喜欢你
- Eclipse自动生成变量名声明(按方法返回值为本地变量赋值)
- R语言学习
- 搭建游戏服务器的问题笔记
- ActiveListManager API
- 一个故事教你看懂什么是数字证书,它的原理是什么?它的作用是什么?
- 【JavaWeb_Part08】白娘子你就算淹了这深圳,我他妈也要去玩我的 Spring
- 洛谷 马的遍历
- linux服务器上下载的csv文件在window环境下用excel打开的乱码问题解决
- 张小龙的微信哲学
- Android学习--RecyclerView的使用
- Codeforces Round #422 (Div. 2) A I'm bored with life
- PHP中的数组
- c++函数重载的原理
- spring项目开发小记