Spring 框架 IOC 与 DI 的总结

一:Spring并天下

1:Spring帝国:

①:Spring崛起

什么是Spring:

		源于Rod Johnson在其著作《Expert one on one J2EE design and development》中阐述的部分

理念和原型的衍生而来.Spring是一个轻量级的DI/AOP容器的开源框架,致力于构建轻量级的JavaEE应用,简化应用

开发,本身涵盖了传统应用开发还拓展到移动端,大数据领域.

什么是容器(Container):
	
		从程序设计角度看就是装对象的对象,因为存在放入,拿出等操作,所以容器还是要管理对象的生命周期,如

Tomcat就是Service和JSP的容器.

		Spring提供了JavaEE每一层的解决方案(full stack)	.Spring其实就是全栈式框架.

Spring与SpringMVC的框架整合:
Spring与SpringMVC的框架整合

②:Spring的优势:

Spring除了不能帮我们写业务逻辑,其余的几乎什么都能帮助我们简化开发.

	:Spring能帮我们低侵入/低耦合地根据配置文件创建及相关对象之间的依赖关系.
	
	:Spring面向切面编程能帮我们无耦合的实现日志记录,性能统计,安全控制等.
	
	:Spring能非常简单的且强大的声明式事务管理.
	
	:Spring提供了与第三方数据访问框架(:Hibemate,JPA)无缝集成,且自己也提供了一套JDBC模板来方便数据库访问.

	:Spring提供与第三方Web(如Struts1/2,JSF)框架无缝集成,且自己也提供了一套Spring MVC框架来方便Web层搭建.
	
	:Spring能方便的与Java Mail,任务调度,缓存框架等技术整合,降低开发难度.

③:Spring帝国

Spring主要产品:

		Spring FrameWork:
	
		Spring帝国之核心,其他Spring其他产品都是基于Spring框架而来.
	
		Spring Boot:
	
		Spring Boot 是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用
		
		的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而是开发人员不在需要定义样板化的配置.
	
		Spring Cloud:Spring cloud微服务框架,为开发者提供了在分布式系统(配置管理,服务发现,熔断,路由,微代理,

		控制总线,一次性token,全居锁,leader选举,分布式session,集群状态)中快速构建的工具,使用Spring Cloud的
		
		开发者可以快速的启动服务或构建应用,同时能够快速和云平台资源进行对接.
	
		Spring Cloud Data Flow: 
	
		Spring Cloud Data Flow简化了专注于数据流处理的应用程序的开发和部署.通过
	
		SpringBoot启动应用,采用Spring Cloud Stream,Spring Cloud Task完成微服务构建.
	
		官网的推荐组合:Spring Boot + Spring Cloud + Spring Cloud Data Flow
	

Spring的其他主要项目版图:
Spring的其他主要项目版图

④:Spring基石

Spring基石,了解一下就行,框住的是我们需要学习的:
Spring基石,了解一下就行,框住的是我们需要学习的

⑤:Spring框架包

Spring框架包包含两大部分:

1:spring-framework-5.X.RELEASE:Spring核心组件(必须).

		docs: Spring开发,帮助文档.
	
		libs: Spring 核心组件的,jar包,源代码,文档.
	
		schema: Spring配置文件的schema约束文件.

2:spring-framework-3.0.5.RELEASE-dependencies:

		Spring依赖的第三方组件(根据需要拷贝),包含了各大开源组织提供的依赖jar,比如日志库,AOP联盟库,连接池库等.
	
		建议使用meve来下载jar包,不需要拷贝jar包了.

⑥:STS工具

	Eclipse: STS工具  Spring Tool Suite基于Eclipse的开发工具.
	
	IDEA:  后面会录制一套IDEA的视频.

2:Spring基础

①:Ioc和DI思想

IoC: Inversion of Control(控制反转):读作"翻转控制",更好理解,不是什么技术,而是一种设计思想,

		好比于MVC.就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理.
	
	正控:若调用者需要使用某个对象,其自身就得负责该对象及该对象所依赖对象的创建和组装.
	
	反控:调用者只管负责从Spring容器中获取需要使用的对象,不关心对象的创建过程,也不关心该对象依赖对象的
	
		创建以及依赖关系的组装,也就是把创建对象的控制权翻转给了Spring框架.

DI: Dependency Injection (依赖注入)从字面上分析: IoC:指将对象的创建权,翻转给了Spring容器:  DI:指Spring

		创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设置值给该对象.

IoC 从字面意义上很难体现出谁来维护对象之间的关系,Martin  Fowler提出一个新的概念--DI,更明确描述了"被注入对象(service对象)
	
	依赖IoC容器来配置依赖对象(DAO对象)".

②:HelloWord程序

依赖jar:
	
	spring-beans-版本.RELEASE.jar
	
	spring-core-版本.RELEASE.jar
	
	报错再添加:
	
	com.springsource.org.apache.commons.logging-1版本.jar
开发jar包

	1:准备jar包
	
	2:开发HelloWorld程序
	
	3:在applicationContext.xml中完成配置(如何获取xsd声明)
	
	4:启动Spring容器
	
	5:从容器中获取指定名称的bean
	
	6:调用bean的方法
什么是BeanFactory:

	BeanFactory是Spring最古老的接口,表示Spring IoC容器--生产bean对象的工厂,负责配置,创建和管理bean

什么是Bean:  被Spring Ioc容器管理的对象称之为bean.

Spring Ioc容器如何知道哪些是它管理的对象:

	此时需要配置文件:Spring Ioc容器通过读取配置文件中的配置元数据,通过元数据对应用中的各个对象进行实例化及装配.

元数据的配置有三种方式(后讲):

	1:XML-based configuration
	
	2:Annotation-based configuration
	
	3:Java-bean configuration

Spring IoC管理bean的原理:

	1:通过Resource对象加载配置文件
	
	2:解析配置文件,得到指定名称的bean
	
	3:解析bean元素,id作为bean的名字,class用于反射得到bean实例:
		
	  注意:此时,bean类必须存在一个无参数构造器(和访问权限无关);

	4:调用getBean方法的时候,从容器中返回对象实例;

	结论:就是把代码从JAVA文件中转移到XML.
	

③:getBean方法的三种签名

	//使用Spring框架之后
	@Test
	public void test2() throws Exception {
		HelloWorld world = null;
		//---------------------------------
		//1:从classpath路径去寻找资源问价,创建资源对象
		Resource resource = new ClassPathResource("applicationContext.xml");
		//2:根据资源对象,创建Spring IoC容器对象 
		BeanFactory factory = new XmlBeanFactory(resource);
		//3:从Spring IoC容器中获取指定名称(helllo world)对象
		//签名一:Object getBean(String beanName);//根据bean对象在容器中的名称来取
		//world = (HelloWorld) factory.getBean("HelloWorld");
		//签名二:<T> T getBean(Class<T> requiredType)//按照指定的类型去寻找bean对象
		//world = factory.getBean(HelloWorld.class);
		//签名三:<T> T getBean(String name, @Nullable Class<T> requiredType)根据bean的类型+ID名称去寻找,推荐的
		world = factory.getBean("HelloWorld",HelloWorld.class);
		//---------------------------------
		world.sayHello();
	}

④:Eclipse提示XML语法

XML需要导入schema约束,约束指向网络路径:

	方式一:连网后,自动缓存路径文件到本地,提供提示功能;
	
	方式二:无连网,需要配置xsd schema文件位置(操作如下图);
	
			:到解压spring/schemas/beans/spring-bean.xsd.
			
			:选择schema location方式.
	
			:复制网络路径 http://www.springframework.org/schema/beans/spring-beans.xsd

⑤:Spring基本配置

<bean id="helloWorld" class="cn.wolfcode.hello.HelloWorld"/>

	name跟id 以后只需要用id属性就行,表示的意思一样,但是name元素可以用空格隔开不同的名字

<import resource=""/>元素

	在开发中,随着应用规模的增加,系统中<bean>元素配置的数量也会增加,导致applicationContext.xml配置
	
	文件变得非常臃肿,为了提高其可读性,我们可以将一个applicationContext.xml文件分解成多个配置文件,
	
	然后在applicationContext.xml文件中包含其他配置文件即可.
	
	语法如下: <import resource="classpath:cn/wolfcode/hello/hello.xml"/>
	
	使用import元素注意:
		
		1:默认情况下:从classpath的根路径寻找.
	
		2:可以使用前缀来定位文件的基础位置:
			
			①:[classpath:] 后面的文件从classpath路径开始找(推荐);
	
			②:[file]:后面的文件使用文件系统的路径开始找;
	
		注意:只有当框架中实现了Resource接口才能够识别上诉的前缀标识符.

⑥:Spring测试框架

测试依赖:

		Spring-test-版本.RELEASE.jar
	
		Spring-context-版本.RELEASE.jar
	
		Spring-aop-版本.RELEASE.jar
	
		Spring-expression-版本.RELEASE.jar
	//使用Junit4的测试案例
	//运行Spring的jUnit4
	@RunWith(SpringJUnit4ClassRunner.class)
	//上下文配置对象,寻找配置文件的
	//@ContextConfiguration("classpath:cn/wolfcode/spring_test/springtext.xml")
	@ContextConfiguration//默认从测试了路径找    测试类名-context.xml文件
	public class SpringTestTest {
		
		//表示自动按照类型从Spring容器中找到bean对象,并设置给该字段
		@Autowired
		private SomeBean bean; 
		
		@Test
		public void test() throws Exception {
			bean.doWork();
		}
	}
	//使用Junit5方式的测试
	@SpringJUnitConfig
	public class SpringTestTest{
		
		@Autowired
		private SomeBean bean;
	
		@Test
		void testName(){
			bean.doWork();
		}
	}

二: 帝国之剑 IoC

1:IoC

①:IOC容器

	1:SpringIoC容器(Contaner):
	
	  BeanFactory:  Spring 最底层的接口,只提供了IoC功能,负责创建,组装,管理Bean,在应用中,一般不使
	
		           用BeanFactory,而推荐使用ApplicationContext(应用上下文).
	
	   ApplicationContext:接口继承了BeanFactory,除此之外还提供AOP集成,国际化处理,事件传播,统一资源加载等功能.
	
	2:Bean的创建时机(此时不使用Spring Test):
	
		:BeanFactory需要等到获取某一个bean的时候才会创建bean--延迟初始化.
	
		:ApplicationContext在启动Spring容器的时候就会创建所有的bean(Web应用建议).
		
		bean属性中的lazy-init="true"也可以延迟初始化,也可以设置到到schema上面的default-lazy-init="true"

	/**
	 	结论:BeanFactory有延迟初始化的特点,在创建Spring容器的时候,不会立马去创建容器中管理的Bean对象
	 		而是要等到从容器中去获取对象的时候,才去创建对象.
	 
	 */
	//使用BeanFactory
	@Test
	public void testBeanFactory() throws Exception {
		Resource resource = new ClassPathResource("cn/wolfcode/container/ContainerTest-Context.xml");
		BeanFactory factory = new XmlBeanFactory(resource);
		System.out.println("====================");
		Person person = factory.getBean("person",Person.class);
		System.out.println(person);
	}
	
	
	/**
 	结论:在创建Spring容器的时候,就会把容器中管理的bean马上初始化,而不会等到获取bean的时候才去初始化.
 
	 */
	//使用ApplicationContext
	@Test
	public void test2() throws Exception {
		ApplicationContext ctx = new ClassPathXmlApplicationContext("cn/wolfcode/container/ContainerTest-Context.xml");
		System.out.println("============================");
		Person person = ctx.getBean("person",Person.class);
		System.out.println(person);
	}

②:bean实例化方式:

	:构造器实例化(无参数构造器),最标准,使用最多.       (使用比较多)
	
	:静态工厂方法实例化:解决系统遗留问题
	
	:实例工厂方法实例化:解决系统遗留问题
	
	:实现FactoyrBean接口实例化:实例工厂变种,如集成MyBatis框架使用: (使用比较多)
	
		org.mybatis.spring.SqlSessionFactoryBean
	<!--:构造器实例化(无参数构造器),最标准,使用最多 -->
	<bean id="cat1" class="cn.wolfcode.createbean._01_constructor.Cat1"/>
	
	<!--:静态工厂方法实例化:解决系统遗留问题 -->
	<bean id="cat2" class="cn.wolfcode.createbean._02_static_factory.Cat2Factory" 
	factory-method="createInstance"/>
	
	<!--:实例工厂方法实例化:解决系统遗留问题 -->	
	<bean id="cat3" class="cn.wolfcode.createbean._03_instance_factory.Cat3Factory"/>
	<bean id="getcat3" factory-bean="cat3" factory-method="createInstance"/>
	
	<!--:实现FactoryBean接口实例化:实例工厂变种,如集成MyBatis框架使用 -->
	<bean id="dat4" class="cn.wolfcode.createbean._04_factory_bean.Cat4Factory">
		<property name="username" value="你好"></property>
	</bean>

③:bean的作用域:

	在Spring容器中是指其创建的Bean对象相对于其他Bean对象的请求可见范围
	
	<bean id="" scope="作用域"/>
	
	singleton: 单例,在Spring IoC容器中仅存在一个Bean实例 (默认的scope)
	
	proptotype: 多例,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean(),相当于执行new XxxBean();不会再容器启动时创建对象
	
	request: 用于web开发,将Bean放入request范围,request.setAttribute("xxx")在调用一个request获得同一个Bean
	
	session:用于web开发,将Bean放入Session范围,在同一个 Session获得同一个Bean
	
	globalSession:一般用于Porlet应用环境,分布式系统存在全局session概念(单点登录),如果不是porlet环境.
	
	globalSession 等同于Session
	
	Spring5开始出现:websocket, globalSession作废.
	
	在开发中主要使用  scope="singleton"  scope="prototype"
	
	总结: 对于Struts1中的Action使用request, Struts2中的Action使用prototype类型,其他使用singleton

④:bean初始化和销毁

	init-method: 定义初始化方法,在构造器执行之后,立马执行
	
	destroy-method: 定义销毁之前的方法,在销毁执行之前,调用
	
	scope: 设置为"prototype" 不是 单例设计模式, 他不知道你啥时候调用完,所以就不关闭资源  考虑资源来之不易,不易轻易释放
		
	<bean id="ds" class="cn.wolfcode.lifecycle.MyDataSource" scope="singleton"
	init-method="open" destroy-method="close"/>
	
	此方法在Spring测试类可用
	
	如果使用ApplicationContext来创建对象,就得手动关闭资源
	
	@Test
	public void testName1() throws Exception {
		@Cleanup
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("cn/wolfcode/lifecycle/App-Context.xml");
		MyDataSource ds = ctx.getBean("ds",MyDataSource.class);
		ds.doWork();
	}
	
	三种关闭资源方法:最后加  ds.close();     @Clearup;      ctx.registerShutdownHook();

⑤:bean的实例化过程(生命周期)

bean的生命周期: bean从出身--消亡直接的整个过程

BeanFactory:		 延迟初始化特点

ApplicationContext:  在启动Spring容器的时候,就会去创建bean对象

bean的生命周期:
1
2
3

2: DI

①:通过XML配置装配

DI:Dependency Injection(依赖注入)

	从字面上分析:IoC:指对象的创建权,反转给了Spring容器;
	
DI:指Spring创建对象的过程中,将对象依赖属性(常量,对象,集合)通过配置设值给该对象.

什么是注入操作?      setter方法    构造器

注入值的类型:
			
			1):常量值(简单类型):value元素
	
			2):对象 :   ref元素
			
			3):集合 :   对应集合类型元素

通过XML配置装配(不推荐)

	<bean id="dog" class="" autowire="byType" />  autowire: byName  byType  constructor  no

②:setter注入

	注入常量  注入对象  注入集合  跟上面注入方法一样
	<!-- 属性注入:常量类型 -->
	<bean id="employee" class="cn.wolfcode.di_setter.Employee1">
		<property name="name" value="will"></property>
		<property name="age" value="17"></property>
		<property name="salary" value="5000"></property>
	</bean>	
	<!-- 下面这种方法不推荐 -->
	<!-- <bean id="employee" class="cn.wolfcode.di_setter.Employee1" p:name="Lucy" p:age="18" p:salary="1000"/> -->
	
	<!-- 属性注入:对象类型 -->
	<bean id="cat1" class="cn.wolfcode.di_setter.Cat1"></bean>
	<bean id="person" class="cn.wolfcode.di_setter.Person1" >
		<property name="c1" ref="cat1"></property>
	</bean>
	
	<!-- 属性注入:集合类型 -->
	<bean id="collectionBean1" class="cn.wolfcode.di_setter.CollectionBean1">
		<property name="set">
			<set>
				<value>set1</value>
				<value>set2</value>
			</set>
		</property>
		<property name="list">
			<list>
				<value>list1</value>
				<value>list2</value>
			</list>
		</property>
		<property name="array">
			<array>
				<value>array1</value>
				<value>array2</value>
			</array>
		</property>
		<property name="map">
			<map>
				<entry key="key1" value="value1"/>
				<entry key="key2" value="value2"/>
			</map>
		</property>
		<!-- <property name="prop">
			<props>
				<prop key="p1">v1</prop>
				<prop key="p2">v2</prop>
			</props>
		</property> -->
		<property name="prop">
			<value>
				p1=v1
				p2=v2
				p3=v3
			</value>
		</property>
	</bean>

③:构造器注入

把上面的property换成constructor-arg  即可
<bean id="person2" class="cn.wolfcode.di_constructor.Person2" >
	<constructor-arg name="c2">
			<bean class="cn.wolfcode.di_constructor.Cat2"/>
	</constructor-arg>
</bean>

④:bean元素的继承

多个bean元素共同配置的抽取,实则是bean配置的拷贝,和Java的继承不同.

	<!-- 多个bean共同配置的抽取 -->
	<bean id="base" abstract="true">
		<property name="name" value="will"></property>
		<property name="age" value="19"></property>
	</bean>
	
	<!-- 配置SomeBase1 -->
	<bean id="someBean1" class="cn.wolfcode.bean_tag_inheritance.SomeBean1" parent="base">
		<property name="weight" value="500"></property>
	</bean> 
	
	<!-- 配置SomeBase2 -->
	<bean id="someBean2" class="cn.wolfcode.bean_tag_inheritance.SomeBean2" parent="base">
		<property name="age" value="99"></property>
		<property name="color" value="业楼"></property>
	</bean>

⑤:配置数据库连接池

	@RunWith(SpringJUnit4ClassRunner.class)
	@ContextConfiguration
	public class App {
		
		@Autowired
		private DataSource ds;
		
		@Test
		public void testName() throws Exception {
		  /*ds = new DruidDataSource();
			ds.setDriverClassName("com.mysql.jdbc.Driver");
			ds.setUrl("jdbc:mysql://localhost:3306/springdemo");
			ds.setUsername("root");
			ds.setPassword("111111");
			ds.setInitialSize(2);*/
			
			@Cleanup
			Connection conn = ds.getConnection();
			@Cleanup
			PreparedStatement ps = conn.prepareStatement("SELECT * FROM student");
			@Cleanup
			ResultSet rs = ps.executeQuery();
			while(rs.next()){
				System.out.print(rs.getLong("id")+",");
				System.out.print(rs.getString("name")+",");
				System.out.println(rs.getInt("age")+",");
			}
		}
	}

⑥:property-placeholder

	<!-- 
     		先配置schema属性
     		然后就可以使用context:property-placeholder标签了
     		从classpath:db.properties文件中去加载资源
     		
     		system-properties-mode="NEVER"表示不从系统中找属性,因为系统中有个也叫
     		username的属性名称,JDBC连接池的属性名称相同,有冲突
     		
     		最好在properties文件中属性前面加个JDBC.
     -->
	 <!-- 从classpath的跟路径去加载db.properties文件 -->
		<context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>
	
		
	<!-- 配置一个druid的连接池  -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
		init-method="init" destroy-method="close" >
		<property name="driverClassName" value="${jdbc.driverClassName}"></property>
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<property name="initialSize" value="${jdbc.initialSize}"></property>
	</bean>

⑦:模拟用户注册的例子

查看我的Eclipse代码,利用xml配置的方式回顾了IoC跟DI.

domain

@Setter@ToString@Getter
public class User {
	private Long id;
	private String name;
	private int age;
}

dao

public interface IUserDAO {
	
	void save(User u);
}

impl

public class IUserDAOImpl implements IUserDAO{
	
	@Setter
	private DataSource ds;
	
	@SneakyThrows
	public void save(User u){
		System.out.println("保存操作");
		@Cleanup
		Connection conn = ds.getConnection();
		String sql = "INSERT INTO user (name,age) values (?,?)";
		@Cleanup
		PreparedStatement ps = conn.prepareStatement(sql);
		ps.setString(1,u.getName());
		ps.setInt(2, u.getAge());
		ps.executeUpdate();
	}
}

service

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

impl

public class UserServiceImpl implements IUserService{
	
	private IUserDAO dao;
	
	public void setDao(IUserDAO dao) {
		this.dao = dao;
	}
	
	@SneakyThrows
	public void register(User user){
		System.out.println("注册操作");
		dao.save(user);
	}
}

action

//模拟Struts2的Action/SpringMVC的Controller
public class UserAction {
	
	@Setter
	private IUserService service;
	
	public String execute() throws Exception{
		System.out.println("注册请求");
		service.register(new User());
		return "success";
	}
}

app

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	
	@Autowired
	private UserAction userAction;
	
	@Test
	public void testRegister() throws Exception {
		userAction.execute();
	}
}

app-Context.xml

		<!-- 从classpath的跟路径去加载db.properties文件 -->
        <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>
        <!-- 配置一个druid的连接池  -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
        init-method="init" destroy-method="close">
        	<property name="driverClassName" value="${jdbc.driverClassName}"></property>
			<property name="url" value="${jdbc.url}"></property>
			<property name="username" value="${jdbc.username}"></property>
			<property name="password" value="${jdbc.password}"></property>
			<property name="initialSize" value="${jdbc.initialSize}"></property>
        </bean>
        
        <!-- 配置DAO -->
        <bean id="userdao" class="cn.wolfcode.register.dao.impl.IUserDAOImpl">
        	<property name="ds" ref="dataSource"></property>
        </bean>
        
        <!-- 配置Service -->
        <bean id="UserService" class="cn.wolfcode.register.service.impl.UserServiceImpl">
        	<property name="dao" ref="userdao"></property>
        </bean>
        
        <!-- 配置
        	如果使用Struts2的Action:此时bean的作用域应该是多例: scope="prototype"
        	如果使用SpringMVC的Controller: 此时bean的作用域依然还是使用单例:singleton /或者不写	
        -->
        <bean id="userAction" class="cn.wolfcode.register.action.UserAction" scope="prototype">
        	<property name="service" ref="UserService" ></property>
        </bean>

3:使用注解配置

①:DI注解

Autowired和Qualifier注解

Spring规范提供

	1:可以让Spring自动的把属性的对象找出来,并注入到对象.
	
	2:可以贴在字段或者setter方法上面
	
	3:可以同时注入多个对象
	
		@Autowired
		public void setter(OtherBean otherBean,OtherBean other2){}
	
	4:可以注入一些Spring内置的重要对象,比如BeanFactory,ApplicationContext,ServiceContext等;
	
	5:默认情况下Autiwrired注解必须要能找到对应的对象,否则报错.
		
		通过required=false来避免这个问题:@Autowired(required=false)
	
	6:第三方程序:Spring3.0之前,需要手动配置Autowired注解的解析程序:
		
		<context:annotation-config/>在Web开发中必须配置
	
	7:Autowired注解寻找bean的方法:
		
		1):首先按照依赖对象的类型找,如果找到,就是用setter或者字段直接注入
	
		2):如果Spring上下文中找到多个匹配类型,再按照名字去找,如果没有 匹配报错;
	
		3):可以通过使用@Qualifier("name")标签来规定依赖对象按照bean的id和类型的组合方式去找;

Resource

DI注解:

		Spring官方:  Autowired
	
		JavaEE规范:  Resource

共同点:  都需要配置DI注解解析器:  <context:annotation-config/>

不同点:	Resource注解必须要能找到对应的对象,否则报错.

		Resource注解首先按照名字去找,如果找到,就使用setter或者字段注入;
		
		如果按照名字找不到,再按照类型去找,但如果找到多个匹配类型,报错;
		
		Resource可以直接使用name属性指定bean的名称(@Resource(name="名字"));但是

			如果指定的name,就只能按照name去找如果找不到,就不再按照类型去找

Value

注入:
		常量类型:   value       Value
	
		对象类型:   ref         Autowired/Resource
		
		@Value("${service.port}")
		private int port;
		
		<!--需要加载的配置文件用 逗号 隔开-->
		<context:property-placeholder location="classpath:db.properties,classpath:server.properties"/>	

②:IoC注解

Component注解和其stereotype注解

	//注解配置:@Component
	@Component("myDataSource")//组件如果不写value属性值,此时bean的id默认是类型首字母小写;
	public class MyDataSource {
		
	}
	
	<!-- IoC注解解析器 -->
	<context:component-scan base-package="cn.wolfcode.ioc"/>
bean组件版型:四个组件的功能是相同的,只是用于标注不同类型的组件.

	@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注.
	
	@Repository用于标注数据访问组件,DAO组件.
	
	@Service用于标注业务层组件.
	
	@Controller用于标注控制层组件(如struts中的Ation,SpringMVC的Controller).
	
	他们几个的功能跟component功能其实是一模一样的.优先使用下面3种注解,当不属于其他组件再使用component

③:Scope 和 PostConstruc 以及 PreDestroy 注解

@PostConstruct用于贴在初始化方法上

@PreDestroy用于贴在销毁方法上

	@Component
	@Scope("singleton")
	public class SomeBean {
		
		public SomeBean(){
			System.out.println("构建SomeBean对象");
		}
		
		@PostConstruct//构建对象之后
		public void open(){
			System.out.println("初始化方法");
		}
		
		@PreDestroy//销毁之前
		public void close(){
			System.out.println("销毁前扫尾方法");
		}
		
		public void doWork(){
			System.out.println("工作");
		}
	}
	
	之后记得写IoC注解解析器
	<context:component-scan base-package="cn.wolfcode.lifecycle"/>

④:使用注解完成注册案例

注意:
	
	使用注解并不能完全取代XML的配置
	
	比如配置连接池DruiDataSource,我们就不能到这个类中去贴注解.
	
	JavaConfig + 注解
	
	@setter注解贴在字段上面仅仅是为我们生成一个Setter方法,本身不能完成注入操作.
	
	@Autowired注解贴在字段上面,自动从Spring 容器中去找到匹配的对象,并设置给该字段.

IoC和DI其实是一个东西:

	IoC:字面上,更多强调的是Spring帮我们创建对象.
	
	DI:字面上,Spring不仅帮我们创建对象,还要为该对象设置依赖的数据.

	最后学会用XML与注解完成注册案例配置

domain

@Setter@ToString@Getter
public class User {
	private Long id;
	private String name;
	private int age;
}

dao

public interface IUserDAO {
	
	void save(User u);
}

impl

@Repository
public class IUserDAOImpl implements IUserDAO{
	
	@Autowired
	private DataSource ds;
	
	@SneakyThrows
	public void save(User u){
		System.out.println("保存操作");
		@Cleanup
		Connection conn = ds.getConnection();
		String sql = "INSERT INTO user (name,age) values (?,?)";
		@Cleanup
		PreparedStatement ps = conn.prepareStatement(sql);
		ps.setString(1,u.getName());
		ps.setInt(2, u.getAge());
		ps.executeUpdate();
	}
}

service

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

impl

@Service
public class UserServiceImpl implements IUserService{

	@Autowired
	private IUserDAO dao;
	
	@SneakyThrows
	public void register(User user) {
		System.out.println("注册操作");
		dao.save(user);
	}
}

action

@Component//变现层
public class UserAction {
	
	@Autowired
	private IUserService service;
	
	public String execute() throws Exception{
		System.out.println("注册请求");
		service.register(new User());
		return "success";
	}
}

APP

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	
	@Autowired
	private UserAction userAction;
	
	@Test
	public void testRegister() throws Exception {
		userAction.execute();
	}
}

APP-context.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
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        " >
        
        <!-- DI注解解析器 -->
        <context:annotation-config/>
        <!-- IoC注解解析器 -->
        <context:component-scan base-package="cn.wolfcode"/>
        
        <!-- 从classpath的跟路径去加载db.properties文件 -->
        <context:property-placeholder location="classpath:db.properties" system-properties-mode="NEVER"/>
        <!-- 配置一个druid的连接池  -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
        init-method="init" destroy-method="close">
        	<property name="driverClassName" value="${jdbc.driverClassName}"></property>
			<property name="url" value="${jdbc.url}"></property>
			<property name="username" value="${jdbc.username}"></property>
			<property name="password" value="${jdbc.password}"></property>
			<property name="initialSize" value="${jdbc.initialSize}"></property>
        </bean>
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值