spring的入门(IOC)
摘要:为什么学习spring
- 方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬編码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。 - AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统O0P实现的功能可以通过AOP轻松应付。 - 声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质
量。 - 方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里 ,测试不再是昂贵的操作,而是随手可做的事情。例如: Spring对Junit4支持, 可以通过注解方便的测试Spring程序。 - 方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts, Hibemate、Hessian, Quartz) 等的直接支持。 - 降低Java EE API的使用难度
Spring对很多难用的Java EE API (如JDBC, JavaMalil, 远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,
这些Java EE API的使用难度大为降低。
spring的入门
- 下载spring的开发包
官网:http://spring.io/
文件名的解释
docs:Spring的开发规范和API
libs:Spring的开发的jar和源码
schema:Spring的配置文件的约束
依赖的jar包
IOC的解释
IOC: Inversion of Control(控制反转)。
控制反转:将创建对象的权限交给了Spring容器.
- IOC原理
说到IOC的原理 ,首先想到的是java高级编程中的反射,最初学习java的时候,都是通过new来进行的对象创建,是直接在程序里面学死的操作,而现在使用spring容器对bean的管理,现在我们可以注入不同的接口实现类,实现不同的需要求,不需要在代码中进行手动的修改,只需要在配文件修改即可.
- java反射机制可以实现对bean对象的方法,属性,构造方法等的访问
- 反射实现的方式
Class对象的三种反射机制实例化模式
- Object支持的实例化对象通过getClass();获取其对象
Student stu=new Student();
Class<?> class1=stu.getClass();//实例化class类对象
- jvm的直接支持,采用类名.Class();进行实例化class对象
Class<?> class2=Student.class;//实例化class类对象
- 采用的是Class类中的的一个方法叫做:static Class<?> forName(String className) ,通过包名进行实例化,返回Class具有给定字符串名称与类或接口关联的对象.
Class<?> class3=Class.forName("ital10.Student");//实例化class类对象
如果程序找不到这个包名的话,会抛出异常"java.lang.ClassNotFoundException"
反射获取类的结构信息
- 反射获取到类的包名以及父类
获取包名称: public Package getPackage();
获取继承父类: public Class<? super T> getSuperclass();
获取实现父接口: public Class< ?>[ getInterfaces();
- 反射获取到构造方法
1. (获取全部构造方法)Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个Constructor对象,该对象反映此Class 对象表示的类的指定公共构造方法。
2. (获取全部构造方法)Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个Constructor对象,该对象反映此Class对象表示的类或接口的指定构造函数。
3. (获取指定构造方法)Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个Constructor对象,该对象反映此Class 对象表示的类的指定公共构造方法。
4. (获取指定构造方法)Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
返回一个Constructor对象,该对象反映此Class对象表示的类或接口的指定构造 函数。
获取指定的构造方法
- 反射获取到类中的普通的方法
1.反射获取所有的普通方法(包括父类):
Method[] getMethods();
返回一个包含Method对象的数组,这些对象反映了此 Class对象表示的类或接口的所有公共方法,包括由类或接口声明的对象以及从超类和超接口继承的对象。
2.反射获取指定的普通方法(包括父类):
Method getMethod(String name, Class<?>... parameterTypes)
返回一个Method对象,该对象反映此Class对象表示的类或接口的指定公共成员方法
反射获取所有的普通方法(本类):
3.Method[] getDeclaredMethods()
返回一个包含Method对象的数组,这些对象反映此 Class对象表示的类或接口的所有已声明方法,包括公共,受保护,默认(程序包)访问和私有方法,但不包括继承的方法。
反射获取指定的普通方法(本类):
4.Method getDeclaredMethod(String name, Class<?>... parameterTypes)
返回一个Method对象,该对象反映此Class对象表示的类或接口的指定声明方法 。
5.Method类(反射包下面的)
在Method类中的有一个方法叫做,这个方法在通过反射获取到对应的方法的时候,使用此方法可以调用普通方法:
Object invoke(Object obj, Object... args)
解析:String name是指方法名称,后面的Class ,是这个参数的反射
- 反射获取成员属性
获取本类全部成员: public Field[] getDeclaredFields( ) throws SecurityException;
获取本类指定成员: public Field getDeclaredField( String name) throws NoSuchFieldException;
获取父类全部成员: public Field[] getFields() throws SecurityException;
获取父类指定成员: public Field getField(String name) throws NoSuchFieldException;
扩展:
执行调用成员属性的时候,必须先去实例化对象,这个时候才能给他们分配空间
1.设置属性内容: public void set(Object obj, Object value)
2.获取属性内容: public Object get(Object obj)
3.解除封装 void setAccessible(boolean flag)
accessible将此反射对象的标志设置为指示的布尔值。(解除封装的意思),这个方法是来自于 AccessibleObject,说明还可以解除私有方法和解除私有的构造
4.public Class<?> getType();.获取成员属性的类型 //getName();和getSimleName()的区别。获取是完整的类名称(包加上类名称),和部分的名称.
一般是使用field类和Method这个类去实现一个set()方法的使用操作,不使用上面的解除封装,进行设置数据
IOC的好处:在之前学习代码都是写固定的代码格式,不能进行改动,而现在是可进行动态的改动.
spring IOC是如果使用反射来完成对象的基本点
1、读取配置文件,或者包扫描注解属性
2、根据配置文件,通过反射实例化对象
3、给对象注入依赖的属性,给属性注入实例化bean对象
4、放到类似集合结构中,容器调用使用.
核心思想:资源交给spring进行集中管理,资源管理更好,易更改,资源不在是自己创建,而是由spring创建,耦合度降低.
- spring依赖注入(DI)
DI:依赖注入,前提必须有IOC的环境,Spring管理这个类的时候将类的依赖的属性注入(设置)进来
Spring相关配置
-
spring的工厂类
BeanFactory:老版本的工厂类
BeanFactory:调用getBean的时候,才会生成类的实例。ApplicationContext :新版本的工厂类
ApplicationContext继承BeanFactory
ApplicationContext:加载配置文件的时候,就会将Spring管理的类都实例化。
ApplicationContext有两个实现类:
1.ClassPathXmlApplicationContext :加载类路径下的配置文件
2.FileSystemXmlApplicationContext :加载文件系统下的配置文件 -
spring配置
- Schema的配置
- bean标签的配置
id :使用了约束中的唯一约束。里面不能出现特殊字符的。
name :没有使用约束中的唯一约束(理论上可以出现重复的,但是实际开发不能出现的)。里面可以出现特殊字符。
<bean name="/user" class=""/>
<bean id ="user" class=""/>
-
Bean的生命周期的配置
init-method:Bean被初始化的时候执行的方法
destroy-method:Bean被销毁的时候执行的方法(Bean是单例创建,工厂关闭) -
Bean的作用范围的配置
scope:Bean的作用范围
singleton:默认的,Spring会采用单例模式创建这个对象。
prototype :多例模式。
request:应用在web项目中,Spring创建这个类以后,将这个类存入到request范围中。
session:应用在web项目中,Spring创建这个类以后,将这个类存入到session范围中。
globalsession:应用在web项目中,必须在porlet环境下使用。但是如果没有这种环境,相对于session。 -
Bean实例化的方式
—无参构造的方式
public class Bean{
public Bean() {
super() ;
System. out . print1n("Bean的无参数的构造方法执行了...");
}
}
///配置
<bean id= "bean" class="com.ital.spring01.demo.Bean">< /bean>
—静态工厂实例化和实例工厂实例化这里不演示.
- spring的属性注入
1.构造方法的属性注入
<bean id="car" class= "com.ital.spring01.demo.Car">
<constructor-arg name= "name " value= "宝马"/ >
<constructor-arg name= "price" value= "800000"/>
</bean>
2.Set方法的方式的属性注入
<bean id="hello" class="Helloimp.helloimp">
<!-- 成员 -->
<property name="name" value="hhhhh"></property>
</bean>
3.Set设置对象类型的属性
<property name= "car2" ref= "car2"/>
这里的car2是bean对应的id
- P名称空间的属性注入(Spring2.5以后)
- 空间引入:
需要在xml文档中加入
xmIns:p= “http: //www. springframework. org/schema/p” - 通过引入p名称空间完成属性的注入:
写法:
普通属性 p:属性名=”值”
对象属性 p:属性名-ref=”值”
<!-- 改为p名称空间的方式-->
<bean id= "car" class="com.ital.spring01.demo.Car" p:name="小车" p:price= "3000"></bean>
<bean id= "employee" class="com.ital.spring01.demo.Employee" p:name="老王”p:car-ref= "car"></bean>
- SpEL的属性注入(Spring3.0以后)
1.语法表达
SpEL:Spring Expression Language,Spring的表达式语言。
语法:
#{SpEL}
oan id= "carInfo" class= "com.ital.spring01.demo.CarInfo"></bean>
<bean id="car" class= "com. ital.spring01.demo.Car">
<property name= "name" value= "#{carInfo.name}"></property>
<property name= "price" value= "#{carInfo.money()}"></property>
</bean>
<bean id= "employee" class="com.ital.spring01.demo.Employee ">
<property name= "name" value= "#{'小胡'}"></ property>
<property name= "car2" value= "#{car}"></property>
</bean>
- 集合类型等其他注入的操作
<!-- 构造方法注入 -->
<bean id="user" class="java_spring02.User.User">
<constructor-arg index="0" value="武汉"></constructor-arg>
</bean>
<!--Student的bean注入 -->
<bean id="student" class="java_spring02.Student.Student">
<!--常量属性的初始化 -->
<property name="name" value="小明"></property>
<!-- bean的注入 -->
<property name="user" ref="User"></property>
<!--数组属性的初始化 -->
<property name="cid">
<array>
<value>123</value>
<value>456</value>
<value>789</value>
</array>
</property>
<!-- list注入 -->
<property name="books">
<list>
<value>java大法</value>
</list>
</property>
<!--map注入 -->
<property name="hobbies">
<map>
<entry>
<key>
<value>建设银行</value>
</key>
<value>1345678904567</value>
</entry>
</map>
</property>
<!-- set注入 -->
<property name="set">
<set>
<value>123</value>
<value>456</value>
<value>789</value>
</set>
</property>
<!-- null注入 -->
<property name="wif">
<null></null>
</property>
<!-- properties注入 -->
<property name="info">
<props>
<prop key="cid">34567</prop>
<prop key="cname">ahha</prop>
</props>
</property>
</bean>
<!-- p注入 需要属性的set方法-->
<bean id="person" class="java_spring02.User.person" p:name="hax" p:cid="123" p:age="18" p:sex="男"></bean>
<!--c注入 需要类的构造方法 -->
<bean id="person" class="java_spring02.User.person" c:name="hax" c:cid="123" c:age="18" c:sex="男"></bean>
</beans>
- spring分模块开发
- 加载多个配置信息
ApplicationContext applicationContext = new ClassPathXmlApplicationContext ( " applicationContext1.xml" ,
'applicationContex2.xml");
- 在一个配置文件中引入多个配置文件
< import resource= "applicationContext2.xmL "/>
声明参考资料:黑马程序员学习资料