Spring(一)之控制反转和依赖注入

1、sts下载:https://spring.io/tools3/sts/all/

参考博客:https://blog.csdn.net/m0_37920381/article/details/79972438

2、简介:

            spring是一个开源框架,是2003年兴起的一个轻量级的java开发框架,它是为了解决企业应用开发的复杂性而创建的。简单点来说,spring是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架

3、优点:①方便解耦,简化开发(spring就是一个大工厂,专门负责生成bean,可以将所有对象创建和依赖关系维护由spring管理)②支持AOP编程(可以方便实现对程序进行权限拦截,运行监控等功能)③声明事务的支持(只需要通过配置就可以完成对事务的管理,而不需要手动编程)④方便程序的测试(可以通过注解方便的测试spring程序)⑤方便集成各种优秀的框架(spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架的支持)⑥降低javaEE API的使用难度(对开发中一些难用的API如JDBC、远程调用等都提供了封装,使他们使用难度大大降低)。

4、IOC控制反转就是将原本在程序中手动创建对象的控制权,交由spring框架管理。

        控制, IoC 容器控制了对象,主要控制了外部资源获取(不只是对象包括比如文件等)由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转,依赖对象的获取被反转了。

IOC的好处就是解耦,对象和对象之间的耦合度变低了,便于测试、便于功能复用。

第一步:下载spring包(由于现在的架包用的是3.xx所以sts中用的是jdk1.7版本。如果你用jdk1.8及以上版本,在用到开启注解时执行会报错。想用jdk1.8及以上版本就用4.xx及以上的架包)

①spring核心包:spring-framework-3.2.0.RELEASE-dist.zip

下载地址:http://repo.springsource.org/libs-release-local/org/springframework/spring/3.2.8.RELEASE/spring-framework-3.2.8.RELEASE-dist.zip

②spring依赖包:spring-framework-3.0.2.RELEASE-dependencies.zip

第二步:创建web项目,导入spring的jar包。(注意:导入4个核心包:beans、core、context,expression+1个依赖包common-logging.jar,导入时不要导入带有sources的源文件[除非你要看相关类的源码,否则一般不导入])

第三步:写个简单的service并在测试方法中调用。

第四步:springIoC控制发转创建实例

 (1)写个配置文件beans.xml注意:beans.xml在src下创建

<?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">

 
</beans>

(2)在beans.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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

 

       	<!-- 配置一个bean(对象) -->
		<bean id="userService" class="com.gyf.service.UserServiceImpl">
		</bean>

</beans>

(3)编写java代码-->加载beans.xml文件,并从spring容器获取userService对象。

①编写service层接口IUserService:

package com.gyf.service;
public interface IUserService {
 
	public void add();         
}

②编写service层实体类IUserService:


public class UserServiceImpl implements IUserService{
    
	@Override
	public void add() {
		System.out.println("创建用户:");
	}

}

③编写test层测试类Lesson02:

package com.gfy.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.gyf.service.IUserService;
public class Lesson02 {
	    @Test
		public void test() {
 	/*
	//以前使用手动创建对象方式。
	IUserService userService=new UserServiceImpl();
	userService.add();
	*/
    //现在使用从spring中获取对象方式。
	//先加载beans.xml文件
	ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
	//再从spring容器获取userService对象。
	IUserService userService=(IUserService) context.getBean("userService");
	userService.add();
	    } 
}

5、DI(Dependency Injection)依赖注入

   在spring框架负责创建Bean对象时,动态地将依赖对象注入到Bean组件中。

   例子:在UserServiceImpl中提供一个get/set的name方法,在beans.xml中通过property去注入。

在以上代码编写好的基础上:

①在UserServiceImpl中提供一个get/set的name方法:

package com.gyf.service;

public class UserServiceImpl implements IUserService{
	private String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public void add() {
		System.out.println("创建用户:"+name);
	}

	
}

②在beans.xml中通过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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

       	<!-- 配置一个bean(对象) -->
		<!-- spring内部创建对象原理:①解析xml文件,获取类名,id,属性;②通过反射,用类型创建对象; ③给对象赋值。-->
		<bean id="userService" class="com.gyf.service.UserServiceImpl">
  		<!-- 依赖注入数据,调用属性的set方法 -->
		<property name="name" value="zhangsan"> </property> 
		</bean>
</beans>

③编写测试类Lesson02:和上面的一样。执行test()方法后得到的结果:

6、加载spring容器的三种方法

   第一种:ClassPathXmlApplicationContext(最常用)

       ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");

       IUserService user=(IUserService) context.getBean("userService");

       user.add();

   第二种:获取文件系统路径获得配置文件(绝对路径)

     ApplicationContext context=new FileSystemXmlApplicationContext("D:\\sts.work\\day1_spring\\src\\beans.xml");

     IUserService user=(IUserService) context.getBean("userService");

    user.add();

     第三种:使用BeanFactory(了解就行)

     String path="D:\\sts.work\\day1_spring\\src\\beans.xml";

     BeanFactory factory=new XmlBeanFactory(new FileSystemResource(path));

     IUserService user=(IUserService) factory.getBean("userService");

    user.add();

spring内部创建对象原理:①解析xml文件,获取类名,id,属性;②通过反射,用类型创建对象; ③给对象赋值。

7、BeanFactory和ApplicationContext对比

   BeanFactory采取延迟加载,第一次getBean时才会初始化bean。

   ApplicationContext是对BeanFactory的扩展,提供了更多功能。

   例如:国际化处理、事件传递、Bean自动装配、各种不同应用层Context实现。

8、装配bean(xml)(其实就是在bean中写一个标签)

    实例化bean的三种方式:①使用构造方法(即new 对象方式)实例化(即上面 5中beans.xml的做法 );②使用静态工厂方法实例化;③使用实例工厂方法实例化

(1)service层中的静态工厂:

package com.gyf.service;

public class UserServiceFactory1 {
	
		public static  IUserService createUserService() {
			return new UserServiceImpl();
		}
}

service层中的实例工厂:

package com.gyf.service;

public class UserServiceFactory2 {
	
		public   IUserService createUserService() {
			return new UserServiceImpl();
		}
}

(2)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的3种方法 -->
       <!-- 第一种:new 实现类 -->
		<bean id="userService1" class="com.gyf.service.UserServiceImpl">
		<property name="name" value="zhang"> </property>
		</bean>
		 <!-- 第二种:通过静态工厂方法 -->
		 <bean id="userService2" class="com.gyf.service.UserServiceFactory1" factory-method="createUserService">
		 <property name="name" value="张三"> </property>
		 </bean>
		 
		 <!-- 第三种:通过实例工厂方法 -->
		  <bean id="factory2" class="com.gyf.service.UserServiceFactory2" > </bean>
		 <bean id="userService3" factory-bean="factory2" factory-method="createUserService">
		 <property name="name" value="小胡"> </property>
		 </bean>
</beans>

  (3)测试类的写法:

package com.gfy.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.gyf.service.IUserService;
import com.gyf.service.UserServiceFactory1;
import com.gyf.service.UserServiceFactory2;


public class Lesson03 {
      
	    @Test
		public void test() {
	       /*
	    	//new 对象
	    	ApplicationContext context1=new ClassPathXmlApplicationContext("beans3.xml");
	    	IUserService userService1=(IUserService) context1.getBean("userService1");
	    	userService1.add();
	    	*/
	    	/*
	    	//通过静态工厂方法
	    	ApplicationContext context2=new ClassPathXmlApplicationContext("beans3.xml");
	    	IUserService userService2=(IUserService) context2.getBean("userService2");
	    	userService2.add();
	    	//
	    	 */
	    	 
	    	//通过实例工厂方法
	    	ApplicationContext context3=new ClassPathXmlApplicationContext("beans3.xml");
	    	IUserService userService3=(IUserService) context3.getBean("userService3");
	    	userService3.add();
	    	
	    	
	    } 
}

9、bean的作用域

①singleton (单例):在spring IOC容器中只存在一个Bean实例,bean以单例方式存在(标记为拥有singleton的对象定义,在Spring的IOC容器中只存在一个实例,所有对该对象的引用将共享这个实例。该实例从容器启动,并因为第一次请求而初始化之后,将一直存活到容器退出。);②prototype (多例)每次从容器中调用bean时都会返回一个新的实例(拥有prototype的bean定义,容器在接到该类型对象的请求的时候,会每次都重新生成一个新的对象实例给请求方,虽然这种类型的对象的实例化以及属性设置等工作都是由容器负责的,但是只要准备完毕,并且对象实例返回给请求方之后,容器就不在拥有当前返回对象的引用。);③request 每次http请求都会创建一个新的bean(XmlWebApplicationContext会为每个http请求创建一个全新的request-processor对象供当前请求使用,当请求结束后,该对象实例的生命周期即告结束。request可以看做是prototype的一种特例,除了应用场景更加具体。);④session 同一个http session共享一个bean,不同的session使用不同的bean(Spring容器会为每个独立的session创建属于他们自己的全新的对象实例,与request相比,除了拥有更长的存活时间,其他没什么差别。);⑤globalsession 一般用于portlet环境(只在基于portlet的web应用程序中才有意义)。

         不写scope="prototype"时默认是单例:

    多例时要加上scope="prototype"

10、bean的生命周期

(1)实例化bean对象(通过构造方法或者工厂方法);(2)设置对象属性(setter等)(依赖注入);(3)如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。(设置bean名字);(4)如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身(bean工厂);(5)预处理,将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法(6)属性赋值完成;(7)调用Bean的初始化方法,自定义的初始化方法;(8)后处理(将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法;(9)使用Bean;(10)容器关闭之前,先调用Bean自己的销毁方法再调用自定义的销毁方法。

11、依赖注入Bean属性(xml)

        依赖: 我的A对象中引用了B对象,也就是说A对象依赖B对象。你要通过配置文件告诉Spring你的对象之间的依赖关系。

        注入: 你的对象已经交给Spring管理了,你也告诉Spring你的对象之间的依赖关系了,那么在合适的时候,由Spring把你依赖的其他对象(或者资源、常量等)注入给你。

    (1)手动装配,使用xml配置(构造方法注入和set方法)

①modle层创建student类:

package com.gyf.model;

public class Student {
 
	private String username;
	private String password;
	private int age;
	
	public String getName() {
		return username;
	}
	
	public void setName(String username) {
		this.username= username;
	}
	
	public String getPassword() {
		return password;
	}
	
	public void setPassword(String password) {
		this.password = password;
	}
	
	public int getAge() {
		return age;
	}
	
	public void setAge(int age) {
		this.age = age;
	}
	
	public Student() {}
	public Student(String username, String password) {
		super();
		this.username = username;
		this.password = password;
	}
	public Student(String username, int age) {
		super();
		this.username = username;
		this.age = age;
	}
	
	
	
	public Student(String username, String password, int age) {
		super();
		this.username = username;
		this.password = password;
		this.age = age;
	}

	@Override
	public String toString() {
		return "student [stname=" + username + ", password=" + password + ", age=" + age + "]";
	}
	
    	
	
	
}

②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 id="st" class="com.gyf.model.Student" scope="prototype" > -->
    <!-- 1、 构造方法注入属性值 -->
     <!-- 相当于调用public Student(String username, String password)构造方法 --> 
<!--   <constructor-arg index="0" value="gyf" type="String"></constructor-arg>
    <constructor-arg index="1" value="123" type="String"></constructor-arg> 
-->   
     <!-- 相当于调用public Student(String username, int age)构造方法 --> 
  <!--  <constructor-arg index="0" value="gyf" type="String"></constructor-arg>
    <constructor-arg index="1" value="123" type="int"></constructor-arg> 
   --> 
  <!--    </bean> -->
  <!-- 2、 set方法注入属性值 --> 
  <bean id="st" class="com.gyf.model.Student" scope="prototype" >
      <property name="password" value="123"></property>
      <property name="age" value="24"></property>
   </bean>
     
      
</beans>

  ③test层的测试类 Lesson06写法:

package com.gfy.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.gyf.model.User;
import com.gyf.model.Student;
import com.gyf.service.IUserService;


public class Lesson06 {
      
	    @Test
		public void test() {
	       
	    	ApplicationContext context=new ClassPathXmlApplicationContext("beans6.xml");
	    	Student stu= (Student) context.getBean("st");
	    	System.out.println(stu);
	    }
}

  SpEL表达式(spring表达式)

       对<property> 进行统一编程,所有内容都使用value

     <property name="" value="#{表达式}"></property>

         #{123}、#{javsd}表示数字、字符串

        #{beanld}表示另一个bean引用

       #{beanld.propName}表示操作数据

       #{beanld.toSpring()}表示执行方法

      #{T(类).字段/方法}表示静态方法或者字段

(2)集合的注入

   集合的注入都是给<property>标签添加子标签

   数组<array>、List<list>、Ste<set>、Map<map>(map存放key/value键值对,使用<entry>描述)、properties:<props> <prop      key=””></prop>

    普通数据<value>、引用数据<ref>

①model层Programmer类的编写

package com.gyf.model;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class Programmer {
    
	/*
	 * 程序员工程师
	 */
	private List<String> Cars;//车
    private Set<String>  pats;//宠物
    private Map<String, String> information;//信息
	private Properties mysqlinfos;//数据库连接信息
	private String[]  members;//家庭成员
	
	public List<String> getCars() {
		return Cars;
	}

	public void setCars(List<String> cars) {
		Cars = cars;
	}

	
	public Set<String> getPats() {
		return pats;
	}

	
	public void setPats(Set<String> pats) {
		this.pats = pats;
	}

	
	public Map<String, String> getInformation() {
		return information;
	}

		public void setInformation(Map<String, String> information) {
		this.information = information;
	}

				public Properties getMysqlinfos() {
			return mysqlinfos;
		}

		
		public void setMysqlinfos(Properties mysqlinfos) {
			this.mysqlinfos = mysqlinfos;
		}

		
		public String[] getMembers() {
			return members;
		}

		
		public void setMembers(String[] members) {
			this.members = members;
		}

	
	
	
	
}

②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 id="programmer" class=" com.gyf.model.Programmer">
         <property name="cars">
            <list>
                <value>ofo</value>
                <value>mobai</value>
                <value>宝马</value>
                <value>ofo</value>
            </list>
         </property>
         
         <property name="pats"> 
            <set>
                 <value>小黑</value>
                 <value>小白</value>
                 <value>小黄</value>
            </set>
         </property>
         
         <property name="information">
            <map>
                <entry key="name" value="dghs"></entry>
                <entry key="sex" value="男"></entry>
                <entry key="age" value="13"></entry>
            </map>
         </property>
         
         <property name="mysqlinfos">
            <props>
                <prop key="url" >mysql:jdbc://localhost:3306/dbname</prop>
                <prop key="user">root</prop>
                <prop key="password">123456</prop>
            </props>
         </property>
         
         <property name="members">
              <array>
                  <value>弟弟</value>
                  <value>妹妹</value>
                  <value>哥哥</value>
                  <value>姐姐</value>
              </array>
         </property>
         
      </bean> 
     
      
</beans>

③test层类Lesson09的编写:

package com.gfy.test;

import java.lang.reflect.Member;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.gyf.model.User;
import com.gyf.model.Programmer;
import com.gyf.model.Student;
import com.gyf.service.IUserService;


public class Lesson09 {
      
	    @Test
		public void test() {
	      
	    	ApplicationContext context=new ClassPathXmlApplicationContext("beans9.xml");
	    	Programmer programmer=   (Programmer) context.getBean("programmer");
	    	System.out.println("车"+programmer.getCars());
	    	System.out.println("宠物"+programmer.getPats());
	    	System.out.println("信息"+programmer.getInformation());
	    	System.out.println("数据库连接信息"+programmer.getMysqlinfos());
	    	System.out.println("家庭成员");
	    	for (String member:programmer.getMembers() ) {
				System.out.println(member);
			}
	    }
}

(3)注解注入(注解就是一个类,使用@注解名称;开发中使用注解代替xml配置文件)

①  @Component(它取代<bean class=””>)

      @Component(“id”)取代<bean id=”” class=””>

      Web开发,提供3个@Component注解衍生注解功能(功能一样)取代<bean class=””>

     @Repository(“名称”):dao层

     @Service(“名称”):service层

     @Controller(“名称”):web层

②  @Autowired:自动根据类型注入

     @Qualifier(“名称”):指定自动注入的id的名称

③ @Resource(“名称”)

    @PostConstruct 自定义初始化

    @PreDestroy  自定义销毁

注解开启:

Xml中的class=“”的路径一定要注意,不然很容易出错误

@Scope("prototype")   //多例注解

使用注解时,web-service-dao配置流程:

①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"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                        https://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        https://www.springframework.org/schema/context/spring-context.xsd">
        
     
    <!-- 开启注解 -->
     <context:annotation-config/> 
    <!-- 注解的位置 -->
    <context:component-scan base-package="com.gyf" /> 
   
      
</beans>

②Dao层:

接口:

package com.gyf.dao;

import com.gyf.model.User;

public interface IUserDao {
       public void add(User user);
}

实体类:

package com.gyf.dao;

import org.springframework.stereotype.Repository;

import com.gyf.model.User;

@Repository      //Dao层
public class UserDaoImpl implements IUserDao {

	@Override
	public void add(User user) {
		System.out.println("Dao添加用户"+user);

	}

}

③service层

接口:

package com.gyf.service;

import com.gyf.model.User;

public interface IUserService {
   
	public void add();
    public void add(User user);           
}

实体类:

package com.gyf.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import com.gyf.dao.IUserDao;
import com.gyf.model.User;

@Service("myUserService")     //service层
//@Component("userService")
public class UserServiceImpl implements IUserService{
    
	@Autowired//sprong会自动往userDao赋值
	private IUserDao userDao;
	private String name;
	
	
	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	@Override
	public void add() {
		System.out.println("创建用户:"+name);
	}


	@Override
	public void add(User user) {
		System.out.println("service添加用户:"+user);
		//调用Dao
		userDao.add(user);
	}

/*
	public IUserDao getUserDao() {
		return userDao;
	}


	public void setUserDao(IUserDao userDao) {
		this.userDao = userDao;
	}
	*/
    
	
}

④web层

package com.gyf.web.action;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;

import com.gyf.model.User;
import com.gyf.service.IUserService;



@Controller    //Web层
public class UserAction {
 
	
	@Autowired //spring会自动为userService赋值
	@Qualifier("myUserService") //根据指定id注入属性
	private IUserService userService;
	

/*
	public IUserService getUserService() {
		return userService;
	}
	public void setUserService(IUserService userService) {
		this.userService = userService;
	}
*/


	public void save(User user) {
		System.out.println("action save 方法:");
		userService.add(user);
	}
}

⑤modle层:

package com.gyf.model;

public class User {

	private String username;
	private String password;
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		System.out.println("2.赋值属性"+username);
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	
	public User() {
		System.out.println("1实例化。。。。");
	}
	@Override
	public String toString() {
		return "User [username=" + username + ", password=" + password + "]";
	}
	
	
	
}

⑥测试层

package com.gyf.test;


import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.gyf.web.action.UserAction;
import com.gyf.model.User;

import com.gyf.service.IUserService;


public class Lesson12 {
      
	    @Test
		public void test() throws Exception {
	      //注解的使用
	    	//web开发流程:cation->service->dao
	    	ApplicationContext context= new ClassPathXmlApplicationContext("beans12.xml");
	    	//获取action
	    	UserAction userAction=context.getBean(UserAction.class);
	    	//添加用户
	    	User user=new User();
	    	user.setUsername("sfjh");
	    	user.setPassword("332");
	    	userAction.save(user);
	    	
	    }
	    
	    
}

 

在eclipse中spring的xml配置文件标签中class路径全限定名自动提示设置

参考:https://www.cnblogs.com/xk920/p/9794711.html

STS中创建 javaweb 项目?参考:https://www.cnblogs.com/ZXF6/p/11066691.html

 

 

 

 

 

 

 

 

 

 

 

 

发布了57 篇原创文章 · 获赞 36 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/hqy1719239337/article/details/97779398