Spring_第一章(IOC)

目录

1:什么是Spring

1.1:Spring概述

1.2:spring框架的好处(结合Spring体系结构分析)

2:Spring的IOC

2.1:未使用Spring的Ioc之前

2.2:使用Spring的Ioc之后

3:SpringBean的实例化方式

3.1:构造函数实例化bean(主流bean实例化方法)

3.2:静态工厂

3.3:实例化工厂

4:Bean的生命周期

4.1:代码实例

5:Springbean的属性注入 

5.1:set注入(主流)

5.2:构造函数注入(主流)

5.3:命名空间注入(p:类属性字段)

5.4:SpEl注入(Spring表达式语言注入  #{ 属性})

6:复杂类型注入

7:bean的注解

7.1:bean管理注解     默认使用构造函数实例化(对应上边的Bean实例化方式)

7.2:自动装配注解(对应上边的Springbean的属性注入,不需要set方法)

7.3:xml和注解混合使用


1:什么是Spring

1.1:Spring概述

Spring是java的一个轻量级的开源框架,它最初是由 Rod Johnson 编写的,并且于 2003 年 6 月首次在 Apache 2.0 许可下发布。为了创建性能良好,易于维护,便于测试的java代码。

1.2:spring框架的好处(结合Spring体系结构分析)

要想了解spring的框架的好处,我们需要知道Spring框架的体系结构,spring有很多个模块组成,了扩展性和兼容性很强,不同的spring模块都有各自的优点,我们要想知道Spring的优点,就要熟知Spring的体系结构

Spring的体系结构如下:

2:Spring的IOC

Spring的Ioc功能主要是控制反转、依赖注入

控制反转:是由Spring的核心容器提供的。Ioc的功能主要摆脱类和类之间的强烈依赖性,有我们以前的代码控制类之间互相new创建对象,改成由容器创建对象。

依赖注入:在我们需要某一个类的时候,不用通过new创建,而是根据需求通过配置文件注入需要的类

springIoc之前:

springIoc之后:

2.1:未使用Spring的Ioc之前

代码示例:此处代码耦合性强,不利于维护,牵一发而动全身

// 传统方法直接new出来实现类,耦合性强
	@Test
	public void test() {
		User u = new User(2, "张三", "123456");
		// 1:通过new创建对象,现象接口编程中,类中添加属性方法在实现类中的时候
		// 需要通过new实现类,然后set赋值属性字段
		UserServiceImpl userService = new UserServiceImpl();
		userService.setFile("属性字段");

		// 2: 通过new创建对象,面向接口编程功改变的时候,需要修改代码切换实现类
		// UserService userService1=new UserServiceImpl();

		userService.add(u);
	}

2.2:使用Spring的Ioc之后

通过配置文件有beanFactory来读取配置文件,然后管理所有的ben

代码示例:

// Spring 注入的方式来实现
	@Test
	public void test1() {
		// 创建bean工厂
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
       // 2:通过工厂获取类
		UserService userService = (UserService) applicationContext.getBean("userService");
        //3.调用类方法
		userService.selectById(0);

		((AbstractApplicationContext) applicationContext).close();
	}

配置文件示例:

<!--默认构造方式  bean的初始方法init-method bean的销毁方法destroy-method  -->
	<bean id="userService" class="com.thit.service.impl.UserServiceImpl" >
		<property name="file" value="注入字段"></property>
	</bean>

3:SpringBean的实例化方式(控制反转三种方式 主流的构造函数实例化bean

前边的简单例子我们可以看到可以通过spring配置文件来实例化bean。接下来主要介绍三种bean的实例方式

3.1:构造函数实例化bean(主流bean实例化方法

代码示例:

public class Bean1  {
	
	public Bean1() {
		System.out.println("构造方法创建bean");
	}

   
}

配置文件:

<!--默认无参构造方式  bean的初始方法init-method bean的销毁方法destroy-method  -->
	<bean id="b1" class="com.thit.controller.Bean1">
	</bean>

<!--有参构造方式,无参构造方法删除   -->

 <!--
      lazy-init="true" 懒加载 spring容器加载的时候没有实例化bean 只有获取bean的时候才创建
      scope="singleton" 单例 放到单例池中
      cope="prototype" 多例 使用的时候创建  因为不知道要创建几个,所有使用的时候创建
      init-method="init1" 参数是方法名字  构造函数执行完毕 执行初始化方法
      destroy-method="destory1" 参数是方法名字 构造函数执行完毕 执行销毁化方法(只有单例有效 一个实例可以销毁 多例无效 jvm负责)

      constructor-arg name="id" value="2" 有参构造函数创建bean
    -->
    <bean id="user" name="aaa,bbb,ccc" class="com.thit.pojo.User"
          scope="singleton"
          lazy-init="false"
          init-method="init1"
          destroy-method="destory1">

        <constructor-arg name="id" value="2"></constructor-arg>
        <constructor-arg name="name" value="李四"></constructor-arg>
    </bean>

3.2:静态工厂

代码示例:

public class Bean2 {
	
}

public class Bean2Factory {
	//此处为静态方法
	public static Bean2 creatBean2() {
		System.err.println("静态工厂构建bean2");
		//此处创建bean2
		return new Bean2();
		
	}
}

配置文件:

<!--静态工厂,配置工厂bean,工厂含有生成bean的静态方法, 指定工厂生成bean2的方法 -->
<bean id="b2" class="com.thit.controller.Bean2Factory" factory-method="creatBean2">
	</bean>

3.3:实例化工厂

代码示例:

public class Bean3 {
	
}

public class Bean3Factory {
	//实例工厂:此处非静态方法
	public  Bean3 creatBean3() {
		System.out.println("实例工厂构建bean3");
		//此处创建bean3
		return new Bean3();
		
	}
}

配置文件:

 <!--实例工厂,配置工厂bean  -->
	<bean id="b3Factory" class="com.thit.controller.Bean3Factory" >
	</bean>

	<!-- 指定bean3工厂是b3Factory,然后指定工厂方法 -->
	<bean id="b3"  factory-bean="b3Factory" factory-method="creatBean3">
	</bean>

以上介绍了bean的三种实例换方法,实例化化的bean归Spring的beanFactory来管理这些bean,那么bean的生命周期是怎么样的呢?

4:Bean的生命周期

bean的生命周期细分的话,分为11步,但是其中比较主要的步骤是

第一步:执行构造方法 spring对bean进行实例化,默认bean是单例
第二步: 指定bean的set方法,spring对bean进行依赖注入
第三步: 如果bean实现了BeanNameAware接口,spring将bean的id传给setBeanName()方法

第4.0步: 如果bean实现了BeanFactoryAware接口,执行setBeanFactory(BeanFactory beanFactory)

第四步:如果bean实现了ApplicationContextAware()接口,spring将调用setApplicationContext()方法将应用上下文的引用传入
第五步 :如果bean实现了BeanPostProcessor接口(后置处理器,负责处理所有的bean,会执行多次)spring将调用它们的postProcessBeforeInitialization接口方法(重点

第六步:如果bean实现了InitializingBean接口,spring将调用afterPropertiesSet方法,


第七步 :执行配置spring配置文件中的的bean(init-method="initTest" )的初始化方法(初始化方法重点
 

第八步: 如果bean实现了BeanPostProcessor接口后置处理器,负责处理所有的bean,spring将调用它们的postProcessAfterInitialization接口方法(重点方法,可以拦截指定bean的指定方法

------------------------------------------
第九步 :执行bean自己的方法

-----------------------------------------
第十步:如果bean实现了DisposableBean 接口,执行配置的bean(destroy-method="destryTest")的销毁方法(单例有效)(重点

4.1:代码实例

代码如下:

// 接口
public interface Bean1Intreface {
	public void run() ;
	public void Save();
	public void run1() ;
}

//实现类
//BeanPostProcessor是bean的后置处理器
public class Bean1 implements Bean1Intreface, BeanNameAware, ApplicationContextAware, InitializingBean, DisposableBean {
	String name;
	public Bean1() {
		System.out.println("第一步:构造方法创建bean");
	}
	
	public void run() {
		System.out.println("第九步:执行类的自己的run方法:"+name);
	}
	
	public void	initTest() {
		System.out.println("第七部:执行配置的bean(init-method=\"initTest\" )的初始化方法-----------");
	}
	
	//单例模式才会调用销毁方法,因为多利调用不可控
	
	public void	destryTest() {
		System.out.println("第十一步:执行配置的bean(destroy-method=\"destryTest\")的销毁方法(单例有效)");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		System.out.println("第二步:执行bean的set方法---");
		this.name = name;
	}

	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("第十步:执行spring的销毁方法(单例情况下有效)");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("第六步:属性设置后执行");
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("第四步:获取工厂信息");
	}

	@Override
	public void setBeanName(String name) {
		// TODO Auto-generated method stub
		System.out.println("第三步:获取bean的名字——"+name);
	}
	public void Save() {
		// TODO Auto-generated method stub
		System.out.println("第九步:执行增强save方法--------");
	}

	@Override
	public void run1() {
		// TODO Auto-generated method stub
		
	}		
		
}


//bean的后置拦截器BeanPostProcessor

//bean的后置处理器
public class MyBeanPostProcessor implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("第五步:bean后置处理器初始化bean之前1:"+bean+"\t"+beanName);
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("第八步:bean后置处理器初始化bean之后:"+bean+"\t"+beanName);
		//bean的名字是b1
		
		if (beanName.equals("b1")) {
			System.out.println("增强指定Bean1类");
			
			Object proxy=Proxy.newProxyInstance(
					bean.getClass().getClassLoader(), 
					bean.getClass().getInterfaces(),
					new InvocationHandler() {
						
						@Override
						public Object invoke(Object proxy, Method method, Object[] args) 
								throws Throwable {
							// TODO Auto-generated method stub
							//增强指定的方法
							if("Save".equals(method.getName())) {
								System.out.println("-----增强指定的Save方法-----");
								return method.invoke(bean,args);
							}
							return method.invoke(bean,args);
						}
					});
			return proxy;
		}else {
			return bean;
		}
		
	}

}

配置文件如下:

<!--默认构造方式  bean的初始方法init-method bean的销毁方法destroy-method  -->
	<bean id="b1" class="com.thit.controller.Bean1" 
	scope="singleton" init-method="initTest" destroy-method="destryTest">
	<property name="name" value="天天"></property>
	</bean>
	
	<!-- 自动加载 -->
	<bean class="com.thit.controller.MyBeanPostProcessor"></bean>

结果分析:

5:Springbean的属性注入 (依赖注入方式3种  主流的是set注入和构造函数注入 

5.1:set注入(主流)

代码如下:

public class Student2 {
	private int id;
	private String naem;
	private Student student;

	set--get--方法

	@Override
	public String toString() {
		return "Student2 [id=" + id + ", naem=" + naem + ", student=" + student + "]";
	}


}

配置文件如下:

<!--构造方法注入属性-->
	<bean id="stu1" class="com.thit.ioc.Student">
		<constructor-arg name="id" value="123"></constructor-arg>
		<constructor-arg name="naem" value="张三"></constructor-arg>
	 </bean>
	 
	 <!--set方法注入属性-->
	<bean id="stu2" class="com.thit.ioc.Student2">
		<property name="id" value="111"></property>
		<property name="naem" value="set注入"></property>
		<property name="student" ref="stu1"></property>
	 </bean>

5.2:构造函数注入(主流)

代码如下:

public class Student {
	private int id;
	private String naem;

	public Student() {
		super();
	}

	public Student(int id, String naem) {
		super();
		this.id = id;
		this.naem = naem;
	}
}

配置文件如下:

	<!--构造方法注入属性-->
	<bean id="stu1" class="com.thit.ioc.Student">
		<constructor-arg name="id" value="123"></constructor-arg>
		<constructor-arg name="naem" value="张三"></constructor-arg>
	 </bean>

5.3:命名空间注入(p:类属性字段)

代码如上只需要添加set方法:p

配置文件如下:

	<!--命名空间依赖set方法 p:属性 直接引用-->
	<bean id="stu1" class="com.thit.ioc.Student" p:id="11" p:naem="P命名空间赋值22">
		
	 </bean>
	 
	 <!--命名空间依赖set标签 set方法注入属性-->
	<bean id="stu2" class="com.thit.ioc.Student2"
	p:id="22" p:naem="命名空间赋值22" p:student-ref="stu1">
	
	 </bean>

5.4:SpEl注入(Spring表达式语言注入  #{ 属性})

代码如上无需更改

配置文件如下:

<!--Spel注入 语法是 #{}-->
	<bean id="stu1" class="com.thit.ioc.Student" >
		<property name="id" value="#{'1'}"></property>
		<property name="naem" value="#{'Spel注入111'}"></property>
	 </bean>
	 
	<!--Spel注入 语法是 #{beanid}-->
	<bean id="stu2" class="com.thit.ioc.Student2">
		<property name="id" value="#{'2'}"></property>
		<property name="naem" value="#{'Spel注入222'}"></property>
		<property name="student" value="#{stu1}"></property>
	 </bean>

6:复杂类型注入

代码如下:

	private String[] arrs;//数组注入
	private List<String> list;//list注入
	private Set<String> set;//set注入
	private Map<Integer,String> map;//map注入
	private Properties ps;//Properties注入

省略set get方法

配置文件如下:

 <bean name="stu3" class="com.thit.ioc.Student3" >
	 <!-- 数组注入  -->
		<property name="arrs">
			<list>
				<value>arrs1</value>
				<value>arrs2</value>
				<value>arrs3</value>
				<value>arrs2</value>
			</list>
		</property>
		<!-- list注入  -->
		<property name="list">
			<list>
				<value>list1</value>
				<value>list2</value>
				<value>list3</value>
				<value>list4</value>
			</list>
		</property>
		<!-- set注入  有去重功能 -->
		<property name="set">
			<set>
				<value>set1</value>
				<value>set2</value>
				<value>set3</value>
				<value>set1</value>
			</set>
		</property>
		<!-- map注入  有去重功能 -->
		<property name="map">
			<map>
				<entry key="1" value="map1"></entry>
				<entry key="2" value="map2"></entry>
				<entry key="1" value="map3"></entry>
			</map>
		</property>
		<!-- propre注入  有去重功能 -->
		<property name="ps">
			<props>
				<prop key="p1">aaa</prop>
				<prop key="p2">bbb</prop>
				<prop key="p3">ccc</prop>
				<prop key="p1">ddd</prop>
			</props>
		</property>
	 </bean>
	 

7:bean的注解

前面使用了xml的配置文集管理和注入bean,但是配置文件写起来比较麻烦,可以通过注解来使用。

第一步:导入aop包

第二步:打开注解扫描

<!-- 开启注解扫描 扫描包-->
    <context:component-scan base-package="com.thit.*"></context:component-scan>

7.1:bean管理注解默认使用构造函数实例化对应上边的Bean实例化方式

@Component("bean名字"),能实现对所有的类进行注解,但是Component不利于三层架构,所以一个注解扩展成了三个来对应不同的业务逻辑层。

@Configuration(定义类      相当于配置文件的beans标签,用来替换配置文件,不需要配置文件了)
@Bean(定义方法,返回bean)

------------------------------------------------------------------

@Controller()   //对controller标注

@Service()    //对service标注

@Repository()  //对dao标注

---------------------------------------


@Scope("prototype")   //单例

 @PostConstruct     //注解初始化方法,替代配置

 @PreDestroy  //注解销毁方法,替代配置
 

@Controller("uControl")
@Scope("prototype")
public class UserController {
	
	//不需要set方法
	@Value("controller传输的名字")
	String name;
	
	
//默认按照类型,自动将service注入,当有两个实现类的时候会有问题
//此时通过Qualifier 设置名字注入
//	@Autowired
//	@Qualifier("uService2")
	
//resource注解相当于@Autowired和Qualifier的结合
	@Resource(name="uService1")
	UserService uService;
	
	//注解初始化方法,替代配置
	@PostConstruct
	public void initT(){
		System.out.println("Controller的bean的初始化方法");
	}
	//注解销毁方法,替代配置
	@PreDestroy
	public void destoryT(){
		System.out.println("Controller的bean的销毁方法,单例下有用");
	}
	
	public  void test() {
		System.out.println("第一步:执行controller的方法");
		uService.add();
		System.out.println("----------------------");
		uService.run(name);
	}
	

其他注解

7.2:自动装配注解(对应上边的Springbean的属性注入,不需要set方法

===================================================================

普通属性注入:@value

    //不需要set方法
    @Value("controller传输的名字")
    String name;

====================================================================

类注入:@Autowired+@Autowired    =  @Resource(name="uService1")

方法一:@Autowired(byType) +@Autowired

//默认按照类型,自动将service注入,当有两个实现类的时候会有问题
//此时通过Qualifier 设置名字注入
//    @Autowired
//    @Qualifier("uService2")

 方法二:@Resource(name="")
//resource注解相当于@Autowired和Qualifier的结合(byType 和byName)
    @Resource(name="uService1")
    UserService uService;

====================================================================

7.3:xml和注解混合使用

我们使用xml来配置bean,使用@Resource属性注入。xml和注解分工合作。

需要增加一行配置

	<!-- 开启注解扫描 扫描包-->
	<context:component-scan base-package="com.thit.*"></context:component-scan>
	
	<!-- 单独使用属性注入注解  controller service dao注解用不了 关闭注解扫描-->
	<context:annotation-config></context:annotation-config>

package com.thit.daoImpl;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.*;

import javax.sql.DataSource;



@Configuration

//扫描包 容器会把包和子包下边的注解都扫描到
// 相当于<context:component-scan base-package="com.thit"/>
@ComponentScan("com.thit")

//<!--作用:引入外部文件 在spring中可以直接使用-->
//<context:property-placeholder location="classpath*:db.properties"/>
@PropertySource(value = {"classpath:db.properties"})

//相当于     <import resource="datasource.xml"/>
@Import(OtherBean.class)
public class SpringConfig {

    @Value("${password1}")
    String password;

    @Bean
    public DataSource dataSource1(){
        DruidDataSource dataSource=new DruidDataSource();
        System.out.println("密码:"+password);
        return dataSource;
    }
}





public class OtherBean {

    String name;

//    @Autowired
//    StudentDao studentDao;

    /**
     * 方法的参数注入
     * @value 普通属性
     *
     * @Autowired 自动注入
     * @Qualifier("studentDaoImpl") 指定这个注解也可以注入
     *
     * @return
     */

    @Bean
    public DataSource dataSource2(@Value("${password1}") String username, @Qualifier("studentDaoImpl")
            StudentDao studentDao){
        DruidDataSource dataSource=new DruidDataSource();
        System.out.println("username:"+username);
        //studentDao.add();
        System.out.println("studentDao:"+studentDao);
        return dataSource;
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值