spring入门的使用
在一个完整的业务中,我们有dao层和service层,controller层 先实现一个完整的业务逻辑
实现dao层
package com.sheng.dao;
public interface UserDao {
void getUser`();`
}
实现dao层的接口实现类
package com.sheng.dao;
public class UserDaoImpl implements UserDao{
public void getUser() {
System.out.println("默认获取用户数据");
}
}
实现service接口(接口与dao层接口一样)
package com.sheng.service;
public interface UserService {
void getUser();
}
实现service的接口实现(调用dao层)
package com.sheng.service;
import com.sheng.dao.UserDao;
import com.sheng.dao.UserDaoImpl;
import com.sheng.dao.UserDaoMysqlImpl;
import com.sheng.dao.UserDaoSqlServiceImpl;
public class UserServiceImpl implements UserService{
private UserDao userDao=new UserDaoImpl();
//业务层去调用dao层
public void getUser() {
userDao.getUser();
}
}
实现controller层(这里用test测试来替代)
import com.sheng.dao.UserDaoImpl;
import com.sheng.dao.UserDaoMysqlImpl;
import com.sheng.dao.UserDaoSqlServiceImpl;
import com.sheng.service.UserService;
import com.sheng.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
// 用户实际调用的是业务层,dao层不需要接触!
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoImpl());
userService.getUser();
}
}
那么运行结果如下
倘若我现在要获取mysql用户数据,怎么实现?普通方法是
实现dao层接口实现类
package com.sheng.dao;
public class UserDaoMysqlImpl implements UserDao{
public void getUser() {
System.out.println("msyql获取用户数据库");
}
}
service接口不变
service接口实现类
package com.sheng.service;
import com.sheng.dao.UserDao;
import com.sheng.dao.UserDaoImpl;
import com.sheng.dao.UserDaoMysqlImpl;
import com.sheng.dao.UserDaoSqlServiceImpl;
public class UserServiceImpl implements UserService{
private UserDao userDao=new UserDaoMysqlImpl();
//业务层去调用dao层
public void getUser() {
userDao.getUser();
}
}
注意,service实现类中,我的userdao对象从UserDaoImpl变成了UserDaoMysqlImpl,因为我现在要实现的是获取mysql用户数据,dao'层的对象肯定要变。
实现结果
倘若我要实现sqlservice的数据,是不是要查询实现dao层,service再更换对象?
发现是不是特别麻烦,你要频繁的根据用户的需求去更换不同的对象,那我们怎么样能简化啊实现?其实很简单
以上所有代码均不变,service接口的实现类改变一下
package com.sheng.service;
import com.sheng.dao.UserDao;
import com.sheng.dao.UserDaoImpl;
import com.sheng.dao.UserDaoMysqlImpl;
import com.sheng.dao.UserDaoSqlServiceImpl;
public class UserServiceImpl implements UserService{
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
//业务层去调用dao层
public void getUser() {
userDao.getUser();
}
}
发现什么区别没有,再之前,我是在service的实现类中,直接new的指定对象,但现在我只是声明,但我没有去创造 那我什么时候创造?当然是你要的时候我去创造,再看我们的实现类有什么变化?
import com.sheng.dao.UserDaoImpl;
import com.sheng.dao.UserDaoMysqlImpl;
import com.sheng.dao.UserDaoSqlServiceImpl;
import com.sheng.service.UserService;
import com.sheng.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
// 用户实际调用的是业务层,dao层不需要接触!
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoSqlServiceImpl());
userService.getUser();
}
}
在实现获取user信息之前,我先调用setuserdao,因为我要知道你要实现的是什么业务吧,你要什么业务,你就在setuserdao中创建谁的对象就好,哎嘿,这种就把创建对象的操作交给了用户。
举一个小例子(自己想象的,可以跳过):
你是一家商店的老板,客户来了,他想要买烟,你去烟柜台去拿,他要买水,你又要去水柜台去拿,拿了之后,客户说我不要了,我要可乐,那你又回去帮他换瓶可乐。你是不是总是被客户牵着鼻子走,你不烦,我都烦了,于是啊,你想,你把柜台直接放在外面,客户来了,哎嘿,你要啥,自己去拿去,你要换啥,自己去换去,把控制权交给了用户,那么老板你列,当然是安心扩充自己的业务去啦!
以上我们用指定创建对象,变成了set注入,而set注入就是实现ioc的一种方式
这是我们最原生的业务实现方式,耦合性很高,层层嵌套
那么我们怎么用spring ioc来实现?
很简单,只需要一个配置文件即可,在resources下创建一个beans.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="UserDaoMysqlImpl" class="com.sheng.dao.UserDaoMysqlImpl">
</bean>
<bean id="UserDaoSqlServiceImpl" class="com.sheng.dao.UserDaoSqlServiceImpl">
</bean>
<bean id="UserServiceImpl" class="com.sheng.service.UserServiceImpl">
<!--
rel:是引用spring容器中创建好的对象
value:具体的值,基本数据类型;
-->
<property name="userDao" ref="UserDaoMysqlImpl"></property>
</bean>
</beans>
以上就是一个简单的spring ioc的配置文件 再业务原生方法中,我们会有很多上面介绍到的坏处,对象由我们来创建,
而spring ioc是怎么来处理的,以前是我来创建对象,现在是由ioc来创建对象 什么意思?就是把我们的类交给IOC容器,我们把类型的业务实现好就可以不用管了,用户要实现什么业务,我们要去找serivce的对象,现在直接去ioc里面去找就可以了,因为我把这些权力都给了ioc,
阅读上方的xml文件,想要把对象交给IOC容器,我们需要用到xml中的bean标签,id就为我们的类名,class就是我们类的全路径,类中必然有参数的情况,bean中property标签name属性就是我们类中的属性名,value参数可以为我们类中的属性赋值
用了配置文件后,我们就轻便多了 在test测试类中
import com.sheng.dao.UserDaoImpl;
import com.sheng.dao.UserDaoMysqlImpl;
import com.sheng.dao.UserDaoSqlServiceImpl;
import com.sheng.service.UserService;
import com.sheng.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
// 用户实际调用的是业务层,dao层不需要接触!
// UserServiceImpl userService = new UserServiceImpl();
// userService.setUserDao(new UserDaoSqlServiceImpl());
// userService.getUser();
//获取ApplicationContext,拿到spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//容器在手,天下我有,需要什么就get
UserServiceImpl userServiceImpl = (UserServiceImpl)context.getBean("UserServiceImpl");
userServiceImpl.getUser();
}
}
原来的实现方式就可以注了,
我们只需要通过
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
来读取到我们的bean.xml文件,这样才能获取到参数 有了这个配置文件后,他肯定会读取到我们xml里面的bean,那么多bean,我要用那个? 需要通过
UserServiceImpl userServiceImpl = (UserServiceImpl)context.getBean("UserServiceImpl");
通过读取到配置文件的对象去getBean,你要实现那个业务就获取那个bean id,也就是那个类,你从bean中获取那个类,你就能得到那个类,有了这个类,我就能调用他的方法,然后getUser,这个没什么好说的
需要强调的是bena中的property,因为我们在一个类,会有参数,也会对象作为参数的时候,比如如上
private UserDao userDao;
我们在service中,把dao层作为对象 这个时候我们的property的value就不能用了,应该改为rel,而rel'就指向该类的bean id即可
不同的bena.xml可以相互引用
<import resource="beans.xml"></import>
在当前的bean.xml resource到你想引用的bean.xml即可
接下来给大家说说bean中参数的问题
创建一个实体类(Student)
package com.sheng.pojo;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] book;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private String wife;
private Properties info;
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", address=" + address.toString() +
", book=" + Arrays.toString(book) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + ''' +
", info=" + info +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBook() {
return book;
}
public void setBook(String[] book) {
this.book = book;
}
public List<String> getHobbys() {
return hobbys;
}
public void setHobbys(List<String> hobbys) {
this.hobbys = hobbys;
}
public Map<String, String> getCard() {
return card;
}
public void setCard(Map<String, String> card) {
this.card = card;
}
public Set<String> getGames() {
return games;
}
public void setGames(Set<String> games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
}
package com.sheng.pojo;
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
咱们看看这个Student类,利用不同的类型的数据作为参数,那么这个时候我们在bean中该如何赋值?
且看如下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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- bean的作用域
scope:singletion ;默认为单列模式
prototype:为原型模式 每次从容器中get的时候,都会产生一个新的对象
其他的·request,session,application,这些只能在web开发中使用到
-->
<bean id="address" class="com.sheng.pojo.Address">
<property name="address" value="霍去病"></property>
</bean>
<bean id="student" class="com.sheng.pojo.Student">
<!-- 第一种,普通值注入,value-->
<property name="name" value="徐长卿"></property>
<!-- 第二种,bean注入,rel-->
<property name="address" ref="address"></property>
<!-- 第三种,数组注入-->
<property name="book" >
<array>
<value>西游记</value>
<value>水浒传</value>
<value>红楼梦</value>
<value>三国演义</value>
</array>
</property>
<!-- list-->
<property name="hobbys">
<list>
<value>听哥</value>
<value>打球</value>
</list>
</property>
<!-- map-->
<property name="card">
<map>
<entry key="身份证" value="123"/>
<entry key="银行卡" value="2222"/>
</map>
</property>
<!-- set-->
<property name="games">
<set>
<value>LOL</value>
<value>cf</value>
<value>bob</value>
</set>
</property>
<!-- null-->
<property name="wife">
<null></null>
</property>
<!-- Properties-->
<property name="info">
<props>
<prop key="学号">2020112918</prop>
<prop key="系别">男</prop>
</props>
</property>
</bean>
</beans>
每一个类型的赋值方式如上,自己可以在底下试试
Spring注解
我们会发现随着我们的类越来越多,我们在xml中加入的bean也就越多,这种情况,我们的注解就出现了
我们在开发中有不同层的实现类,我们在注解中也有区分
- @Controller 代表它是一个Controller层的类,在类上加上这个注解功能就相当余在xmlbean了这个类 2.@Repository 代表它是一个dao层类 3.@Component 代表它是一个实体类 4.@Service 代表是一个service层的类
通过注解,我们就可以舍弃xml的方式,两种方式,那么喜欢那种就用那种
注意的是,写上了注解我们还不能用,因为我们要激活它
<context:annotation-config/>
激活注解之后我们还是不能用,嘿嘿嘿,因为我们要进行一次扫描,让容器知道有那些类要当ioc容器中去
<context:component-scan base-package="com.sheng"/>
加上以上两行代码在bean.xml即可,注意base-package的值是你要扫描的包
对于注解的补充
以上四个注解实现的功能都是一样的,主要是为了区分不同的业务层 以@Component举例 @Component("name")等于@Component(value="user") 给当前类的beanid取为user
@Value注解,放在字段上,默认值就为@value("")
@Value("徐长卿") //等价于<property name="" value=""/>
public String name;
@Resource注解 在类中我们会存在字段是一个对象的情况,
@Resource(name = "user")
private User user;
需要用到resource来声明,