(一)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 MVCSpring 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约束。

posted @   高兴518  阅读(93)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示

目录导航