(一)Spring-介绍、对象创建以及依赖注入
作者:互联网
(一)Spring-介绍、对象创建以及依赖注入
一、 简介
-
spring:春天--->给软件行业带来了春天
-
Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情。然后,Sping的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
-
目的:解决企业应用开发的复杂性
-
功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能。
-
范围:任何Java应用
-
-
Spring是一个轻量级
控制反转(IoC)
和面向切面(AOP)
的容器框架。 -
官网地址:
https://spring.io/projects/spring-framework
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html
1.1 Spring的前生
- 2002,首次推出了Spring框架的雏形:interface21框架!
- 2004年3月24号,Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。
- Rod Johnson,是Spring Framework创始人。
- Spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有技术框架。
1.2 Spring特征
- 核心技术:依赖注入、事件、资源、i18n、验证、数据绑定、类型转换、SpEL、AOP。
- 测试:模拟对象、TestContext 框架、Spring MVC 测试、
WebTestClient
. - 数据访问:事务、DAO 支持、JDBC、ORM、编组 XML。
- Spring MVC和 Spring WebFlux Web 框架。
- 集成:远程处理、JMS、JCA、JMX、电子邮件、任务、调度、缓存。
- 语言:Kotlin、Groovy、动态语言。
1.3 Spring的优点
- Spring是一个开源的免费的框架(容器)!
- Spring是一个轻量级的、非入侵式的框架。
控制反转(IoC)
和面向切面(AOP)
- 支持事务的处理,对框架整合的支持。
总结:Spring是一个轻量级的控制反转(IoC)
和面向切面(AOP)
的框架
1.4 Spring的组成
1.5 拓展
在Spring的官网有这个介绍:现代化的Java开发!说白了就是基于spring的开发。
- Spring framework
- Spring Boot
- 一个快速开发的脚手架。
- 基于SpringBoot可以快速的开发单个微服务。
- 约定大于配置!
- Spring Cloud
- SpringCloud是基于SpringBoot实现的
因为现在大多数公司都在使用SpringBoot进行快速开发,学习Springboot的前提,需要完全掌握Spring及SpringMVC!承上启下的作用!
Spring Framework的弊端:发展了太久之后,违背了原来的理念!配置十分繁琐,人称配置地狱。
二、IOC理论推导
2.1 IOC之前的原来模式
1 UserDao接口
package com.happy.dao;
import com.happy.pojo.User;
public interface UserDao {
User getUser();
}
2 UserDaoImpl实现类
package com.happy.dao;
import com.happy.pojo.User;
import com.happy.utils.IDutils;
public class UserDaoMysqlImpl implements UserDao {
@Override
public User getUser() {
// 模拟数据库查询到用户了
User user = new User();
user.setId(IDutils.getId());
user.setPwd("123");
user.setName("happy");
System.out.println("mysql数据库里获取到user了");
return user;
}
}
3 UserService业务接口
package com.happy.service;
import com.happy.dao.UserDao;
import com.happy.pojo.User;
public interface UserService {
// UserDao userDao=null;
public User getUser();
}
4 UserServiceImpl业务实现类
注意:
使用setUserDao来给外界提供接口注入实现。
package com.happy.service;
import com.happy.dao.UserDao;
import com.happy.dao.UserDaoImpl;
import com.happy.dao.UserDaoMysqlImpl;
import com.happy.pojo.User;
public class UserServiceImpl implements UserService {
// UserDao userDao = new UserDaoImpl();
// UserDao userDao = new UserDaoMysqlImpl();
// UserDao userDao=new UserDaoImpl()
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
@Override
public User getUser() {
// UserDao userDao = new UserDaoImpl();
User user = userDao.getUser();
return user;
}
}
5 控制层
package com.happy.servlet;
import com.happy.dao.UserDaoMysqlImpl;
import com.happy.pojo.User;
import com.happy.service.UserService;
import com.happy.service.UserServiceImpl;
import org.junit.Test;
public class TestUserService {
@Test
public void testUserService(){
UserService userService = new UserServiceImpl();
((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl());
User user = userService.getUser();
System.out.println(user);
}
}
6 小结
在我们之前的业务中,用户的需求变更或者实现方式变更可能会影响我们原来的代码,我们需要根据变动去修改源代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!
我们使用了一个Set接口实现,对外暴露,已经发生了革命性的变化!
- 之前,程序是主动创建对象!控制权在程序员手上。
- 使用set注入后,并给外部暴露接口,程序不再具有主动性,而是等待外部被动的接收对象。
这种思想,从本质上解决了问题,我们程序员不用去手动创建和管理对象了,系统的耦合性大大降低,更加专注业务的实现上。这就是IOC的原型!
public class UserServiceImpl implements UserService {
// UserDao userDao = new UserDaoImpl();
// UserDao userDao = new UserDaoMysqlImpl();
// UserDao userDao=new UserDaoImpl()
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
2.2 IOC本质
- 控制反转IoC(Inversion of Contorl),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种方法。没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建移交给第三方,个人认为控制反转就是:获得依赖对象的方式反转了。
- 采用XML方式配置Bean的时候,Bean的定义信息和实现分离的,而采用注解的方式可以把两者合为一体,bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
- 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的事IoC容器,其实现方法时依赖注入(Dependency InJection)
三、Spring入门
3.1 HelloSpring
1 编写bean
package com.happy.pojo;
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
2 编写xml=》注入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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDaoImpl" class="com.happy.dao.UserDaoImpl"></bean>
<bean id="userDaoMysqlImpl" class="com.happy.dao.UserDaoMysqlImpl"></bean>
<bean id="userDaoOracleImpl" class="com.happy.dao.UserDaoOracleImpl"></bean>
<bean id="userService" class="com.happy.service.UserServiceImpl">
<!-- <property name="userDao" ref="userDaoMysqlImpl"></property>-->
<!-- ref是引用spring容器中创建好的对象-->
<property name="userDao" ref="userDaoOracleImpl"></property>
</bean>
</beans>
3 使用bean测试
package com.happy.servlet;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestHelloSpring {
@Test
public void testHelloSpring(){
// ClassPathXmlApplicationContext为ApplicationContext的一个实现
// 获取spring的上下文对象!
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Object hello = context.getBean("hello");
Object hello2 = context.getBean("hello");
System.out.println(hello);
System.out.println(hello==hello2);
}
}
3.2 UserDao的案例
到此,我们继续根据spring来完善第2部分UserDao的案例
1 编写bean
同第二部分1~4部分,编写Service和Dao层的bean
2 编写xml=》注入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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userDaoImpl" class="com.happy.dao.UserDaoImpl"></bean>
<bean id="userDaoMysqlImpl" class="com.happy.dao.UserDaoMysqlImpl"></bean>
<bean id="userDaoOracleImpl" class="com.happy.dao.UserDaoOracleImpl"></bean>
<bean id="userService" class="com.happy.service.UserServiceImpl">
<!-- <property name="userDao" ref="userDaoMysqlImpl"></property>-->
<!-- ref是引用spring容器中创建好的对象-->
<property name="userDao" ref="userDaoOracleImpl"></property>
</bean>
</beans>
3 使用bean测试
package com.happy.servlet;
import com.happy.dao.UserDaoMysqlImpl;
import com.happy.pojo.User;
import com.happy.service.UserService;
import com.happy.service.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestUserService {
@Test
public void testUserService(){
UserService userService = new UserServiceImpl();
((UserServiceImpl) userService).setUserDao(new UserDaoMysqlImpl());
User user = userService.getUser();
System.out.println(user);
}
@Test
public void testUserServiceBySpring(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("userDao.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
User user = userService.getUser();
System.out.println(user);
}
}
四、IOC创建对象方式
4.1 无参构造
默认使用无参构造创建对象
,这是默认的。
<bean id="user" class="com.happy.pojo.User"></bean>
4.2 有参构造的3种方式
1 构造器参数下标
<!-- 第一种方式:通过下标index -->
<bean id="user" class="com.happy.pojo.User">-->
<constructor-arg index="0" value="gaoyiheng"></constructor-arg>-->
</bean>
2 构造器参数类型
不推荐使用!第二种方式不建议使用,同类型不能精确指定,容易混淆。
<!-- 第二种方式:通过下标index -->
<!-- 第二种方式不建议使用,同类型不能精确指定,容易混淆-->
<bean id="user" class="com.happy.pojo.User">
<constructor-arg type="java.lang.String" value="happy518"></constructor-arg>
<constructor-arg type="java.lang.String" value="happyname"></constructor-arg>
</bean>
3 构造器参数名称
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 第三种方式:通过属性的name -->
<bean id="user" class="com.happy.pojo.User">
<constructor-arg name="name" value="gaoxing"></constructor-arg>
<constructor-arg name="id" value="123"></constructor-arg>
</bean>
</beans>
五、Spring配置
Spring的配置很少,总共就下面5个一级标签。
5.1 Alias别名
<bean id="user" class="com.happy.pojo.User">
<constructor-arg name="name" value="gaoxing"></constructor-arg>
<constructor-arg name="id" value="123"></constructor-arg>
</bean>
<bean id="user2" class="com.happy.pojo.User2" scope="prototype">
</bean>
<alias name="user" alias="user1"></alias>
@Test
public void testAlias(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("user.xml");
User user = (User) applicationContext.getBean("user");
User user1 = (User) applicationContext.getBean("user1");
System.out.println(user1);
System.out.println(user==user1);
}
下图可以看到,两个对象都相等,证明为就是一个别名而已。
另一种起别名的方法
用name
<bean id="user" class="com.happy.pojo.User" name="user3">
<constructor-arg name="name" value="gaoxing"></constructor-arg>
<constructor-arg name="id" value="123"></constructor-arg>
</bean>
5.2 Bean的配置
1 name
2 scope
指定bean的作用范围。
<bean id="user" class="com.happy.pojo.User" name="user3">
<constructor-arg name="name" value="gaoxing"></constructor-arg>
<constructor-arg name="id" value="123"></constructor-arg>
</bean>
<bean id="user2" class="com.happy.pojo.User2" scope="prototype">
</bean>
5.3 import
-
这个import,一般用于团队合作开发使用,他可以将多个配置文件导入合并为一个。
-
假设,现在项目中有多个人开发,这三个复制不同的类开发,不同的类开发,不同的类需要注册在不同的bean.xml文件中。我们可以利用import将所有人的beans.xml合并为一个总的。
-
applicationContext.xml一般为spring默认配置文件。所以用这个作为总配置文件,使用的时候使用这个就可以了。
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="user.xml"></import>
</beans>
六、依赖注入
6.1 构造器注入
见第4章节。
6.2 set属性注入
- 依赖注入:set注入属性
- 依赖:属性
- 注入:bean对象中的所有属性,由容器来注入
1 测试对象bean
package com.happy.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private String name;
private String wife;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private Properties info;
}
2 依赖属性-复杂对象bean
package com.happy.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
private String Address;
}
3 配置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 http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.happy.pojo.Student">
<!-- 第一种普通值注入-->
<property name="name" value="happy"></property>
<property name="address" ref="addresss"></property>
<!-- <property name="wife" value="null"></property>-->
<property name="wife">
<null></null>
</property>
<!--array-->
<property name="books">
<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="1234"></entry>
<entry key="储蓄卡" value="4321"></entry>
</map>
</property>
<!--set-->
<property name="games">
<set>
<value>篮球</value>
<value>足球</value>
</set>
</property>
<!--property-->
<property name="info">
<props>
<prop key="username">happy</prop>
<prop key="password">12314</prop>
<prop key="url">jdbc:mysql://localhost/mysql</prop>
</props>
</property>
</bean>
<!-- 复杂对象-->
<bean id="addresss" class="com.happy.pojo.Address">
<property name="address" value="香港"></property>
</bean>
</beans>
4 测试使用
package com.happy.service;
import com.happy.pojo.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Properties;
public class StudentServiceImpl implements StudentService {
@Override
public Student getStudent() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
String wife = student.getWife();
System.out.println(wife);
Properties info = student.getInfo();
System.out.println("info的类型:"+info.getClass());
System.out.println(info.getProperty("url"));
info.setProperty("addkey","addvalue");
System.out.println("info:"+info);
System.out.println(student);
return student;
}
@Test
public void test() {
getStudent();
}
}
6.3 拓展方式注入:P命名空间和C命名空间
我们可以通过P和C命名空间注入依赖
1 p:
p命名空间注入,可以直接注入属性的值:property
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.happy.pojo.User" p:name="happybyP" c:pwd="8888">
<!-- <property name="name" value="happy518"></property>-->
</bean>
</beans>
2 c:
c命名空间注入,通过构造器注入:constructor-args
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.happy.pojo.User" c:pwd="8888">
<property name="name" value="happy518"></property>
</bean>
</beans>
3 使用测试
package com.happy.service;
import com.happy.pojo.Student;
import com.happy.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Properties;
public class StudentServiceImpl implements StudentService {
@Override
public Student getStudent() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
String wife = student.getWife();
System.out.println(wife);
Properties info = student.getInfo();
System.out.println("info的类型:"+info.getClass());
System.out.println(info.getProperty("url"));
info.setProperty("addkey","addvalue");
System.out.println("info:"+info);
System.out.println(student);
return student;
}
@Test
public void test() {
getStudent();
}
@Test
public void testPandC(){
ApplicationContext context = new ClassPathXmlApplicationContext("user.xml");
User user = context.getBean("user", User.class);
System.out.println(user);
}
}
注意点:p命名和C命名空间不能直接使用,需要导入xml约束。
标签:依赖,Spring,User,创建,import,com,public,happy 来源: https://www.cnblogs.com/happycarpediem/p/16254782.html