1.Spring简介
spring是一个可以用于Java任何项目开发的框架,不过由于spring为Java的web开发提供了很多其他的支持,所以spring在Javaweb的开发中使用的十分广泛。spring的主要思想为IOC(控制反转)和AOP(面向切面编程)。IOC指的是将我们在编程时使用的对象交给spring来管理,我们不再需要自己创建对象,每次需要使用一个对象时只需要在spring中来获取这个对象;AOP中的切面在程序中指的是在程序的运行过程中的某一个节点,AOP说的就是在这个点的前面或者后面添加一段程序,实现其他的功能,提高了程序的可扩展性。
2.spring的配置
spring的配置方法分为使用注解配置和在配置文件中配置,这篇文章介绍的是在配置文件中配置,在开发中我们一般使用注解进行配置,但是使用配置文件配置可以帮助我们更好的理解spring的思想,所以最好先掌握了这种方法。
2.1配置头
<?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:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
以上是spring配置文件的配置头,配置头是决定这个xml文件的书写格式的,上面值配置了beans,aop,context,如果需要使用mvc,事务等可以继续添加。
2.2配置IOC
向spring中添加对象,其实就是将一个类配置到spring配置文件中,在程序中加载了配置文件之后spring会自动的为这些类创建对象,所以这个类中必须要有构造方法,在spring创建这些类的对象时,还需要为里面的参数赋一些初值,这里有几种方法。
<bean id="peo1" class="beans.people1">
<!--index参数的索引 name参数名 type参数类型 value基本数据类型的值 ref另一个对象作为初始值
这几个参数主要用来控制调用哪个构造方法 ,默认选择构造方法的顺序是从下到上。-->
<constructor-arg index="0" value="123"></constructor-arg>
<constructor-arg index="1" value="String"></constructor-arg>
</bean>
<!-- 使用set方法为对象赋值 -->
<bean id="peo2" class="beans.people2">
<!-- <property name="id" value="222"></property> -->
<property name="id">
<value>222</value>
</property>
<property name="name" value="sss"></property>
<property name="list">
<list>
<value>list1</value>
<value>list2</value>
<value>list3</value>
</list>
</property>
<property name="map">
<map>
<entry key="a" value="A"></entry>
<entry key="b" value="B"></entry>
</map>
</property>
</bean>
<!-- 依赖注入 -->
<bean id="peo3" class="beans.people3">
<property name="p1" ref="peo1"></property>
<property name="p2" ref="peo2"></property>
</bean>
<bean>
标签代表一个类,spring启动时就会为每一个<bean>
标签里的类创建一个对象。<bean>
里面的<property>
标签是代表类内的属性,<property>
标签的ref属性代表引用这个配置文件里的另一个bean,其他的属性直接看代码就行,关于一个bean(也就是一个类)的属性的初值的设置,上面使用了两种方法,第一种是通过构造方法设置初值,第二种是通过set方法设置初值。最后的依赖注入展示了在一个类中也只另一个类的对象,使用了ref属性。
2.3 配置AOP
AOP的思想是在某一个程序运行的节点的前后执行其他的程序,所以我们需要配置两样东西,一个是在哪一个节点添加,换句话说,就是将哪里设置成我们要添加其他程序的地方,这个地方被叫做切点,其次,我们需要配置在这个切点执行哪里的代码,所要执行的代码我们称作通知,这个通知其实也是一个普通的bean。
配置AOP有两种方法,一种是schma-based,另一种是AspectJ,这两种方法在使用上的区别是schma-based的代码简单,但需要进行很多的配置,AspectJ方法则正好相反,配置简单,代码复杂。我们这里只说第一种方法。
<!-- 前置通知,后面会引用 -->
<bean id="mybefore" class="advice.MyBeforeAdvice"></bean>
<!-- 后置通知 -->
<bean id="myafter" class="advice.MyAfterAdvice"></bean>
<!-- 环绕通知 -->
<bean id="myarround" class="advice.MyArroundAdvice"></bean>
<!-- 形成切面,这里用的是schma-based方法 -->
<aop:config>
<!-- 形成切点 -->
<aop:pointcut expression="execution(* beans.AOPBean.test2())" id="mypoint"/>
<!-- 对切面添加通知, advice-ref:通知名 , pointcut-ref:要作用的切点 -->
<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
<aop:advisor advice-ref="myarround" pointcut-ref="mypoint"/>
</aop:config>
根据以上的代码,先配置通知类的bean,每一个通知类都需要实现一个接口和方法才能使这个通知生效,关于通知的代码在后面。配置了通知类的bean之后,就需要设置切点,将通知配进去, <aop:config>
是配置切点的标签, <aop:pointcut>
用来配置切点的位置,execution(* beans.AOPBean.test2())
代表这个切点的位置是beans包下的AOPBean类中的test2()这个方法,我们可以在这个方法执行之前或之后添加通知,其中的*代表通配符,在想要将一个类的所有方法或者一个包下的类的所有方法都设成切点时可以使用通配符,id
表示这个切点的名字。<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
表示在mypoint这个切点配置mybefore这个通知。
下面是通知类的代码:
前置通知:MyBeforeAdvice.class,在方法执行前执行
public class MyBeforeAdvice implements MethodBeforeAdvice {
/*
* method:切点的方法的位置和名称,基于反射原理
* args:切点方法的参数
* target:切点方法所在的对象
*/
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("切点的方法:"+method+",切点的方法名:"+method.getName());
System.out.println("切点方法的参数:"+args);
System.out.println("切点方法所在的对象:"+target);
System.out.println("这是test2的前置通知");
}
}
后置通知:MyAfterAdvice.class,在方法执行后执行,方法参数的含义与前置通知相同
public class MyAfterAdvice implements AfterReturningAdvice{
/*
* returnValue:切点方法的返回值
*/
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("这是test2的后置通知");
}
}
环绕通知:MyArroundAdvice.class,可以在这一个类里配置前置和后置通知。Object result=invocation.proceed();
这句话表示运行切点的方法
public class MyArroundAdvice implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
System.out.println("这是环绕前置通知");
Object result=invocation.proceed();
System.out.println("这是环绕后置通知");
return result;
}
}
3.spring的使用
配置完成之后,我们就需要使用了,如果是我们自己手动加载配置文件,代码是这样的:
public class IOCTest1 {
public static void main(String[] args) {
ApplicationContext ac=new ClassPathXmlApplicationContext("ApplicationContext.xml");
people1 p1=ac.getBean("peo1",people1.class);
System.out.println(p1);
people2 p2=ac.getBean("peo2",people2.class);
System.out.println(p2);
people3 p3=ac.getBean("peo3", people3.class);
System.out.println(p3);
}
}
可以将ac理解为spring的容器,我们在想要使用某一个类的对象时就可以直接从ac中取。但是这种方法需要我们自己加载配置文件,不是很方便,我们想要在这个程序启动的同时自动加载配置文件,这样使用起来就更加方便了。
要想使程序在启动时自动加载配置文件,就需要配置项目的web.xml文件,在web.xml添加如下代码:
<!-- 上下文参数 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</context-param>
<!-- 监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
ApplicationContext.xml就是我们之前写的配置文件,使用监听器ContextLoaderListener在tomcat启动时自动加载配置文件。这时想要在spring容器中取出对象需要的代码如下:
public class IOCTest1 {
public static void main(String[] args) {
ApplicationContext ac =WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
people1 p1=ac.getBean("peo1",people1.class);
System.out.println(p1);
people2 p2=ac.getBean("peo2",people2.class);
System.out.println(p2);
people3 p3=ac.getBean("peo3", people3.class);
System.out.println(p3);
}
}
其实配置监听器就是将spring容器放入了application中,就是一个web程序中的最大作用域的全局对象,只要服务器不关闭,这个对象就会一直存在。但是一般的时候我们也不会这样使用,会使用spring的自动注入的注解,使用起来很方便。