Spring入门基本概念
Spring概念
spring的作用就是为代码解耦,降低代码间的耦合度。
容器
spring作为容器,可以管理对象的生命周期,对象与对象之间的依赖关系。通过配置文件,定义对象,管理对象之间的依赖关系。
Spirng与Ioc
控制反转,即被调用者的实例不是调用者创建的,而是由spring容器创建的,并注入调用者。当应用了Ioc,一个对象依赖的其他对象会通过被动的方式进来,而不是这个对象主动去创建。容器在对象初始化时不等对象请求就主动将依赖传入。
spring的第一个程序
导入jar包定义接口
public interface IStudentService {
public void some();
}
定义实现类
public class StudentServiceImpl implements IStudentService{
@Override
public void some() {
System.out.println("hello");
}
}
创建spring配置文件
目录下创建一个applicationContext.xml配置文件,文件约束在Spring4\spring-framework-4.2.1.RELEASE\docs\spring-framework-reference\html下找。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
</beans>
配置bean
<bean id="studentService" class="springInit.StudentServiceImpl"/>
定义测试类
@Test
public void test() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
IStudentService bean = (IStudentService)context.getBean("studentService");
bean.some();
}
接口容器
ApplicationContext接口容器
实现类
- FileSystemXmlApplicationContext
- ClassPathXmlApplicationContext
- AnnotationConfigApplicationContext
BeanFactory接口容器。BeanFactory是ApplicationContext接口的父类
实现类
org.springframework.beans.factory.xml.XmlBeanFactory
两个接口容器的区别
虽然这两个接口容器所要加载的spring配置文件是同一个配置文件,但在代码中的这两个容器对象不是同个对象,即不是同一个容器:它们对于容器内对象的装配时机是不同。
ApplicationContext装配时机
ApplicationContext容器会在容器对象初始化时,将其中的对象一次性全部装配好,以后代码中需要,直接在内存中获取即可。执行效率高,但占用内存。
BeanFactory装配时机
BeanFactory容器采用延时加载策略,即在第一次调用getBean()时才会真正装配对象。
Bean
bean是spring管理的基本单位,在基于spring的JavaEE应用中,所有的组件都被当成bean处理。在spring中,bean是一个很广义的概念,任何java对象,组件都被当做bean处理。
Bean的装配
默认装配方式
代码通过getBean的方式,从容器获取指定的bean实例。容器首先会调用bean的无参构造器,创建空值的实例对象
动态工厂Bean
将动态工厂当普通bean使用
在配置文件注册动态工厂bean,通过getBean夺取动态工厂对象后,调用动态工厂方法获取相应目标对象。目标对象的创建不再由spring容器管理。
/动态工厂类
public class serviceFactory {
public IStudentService getStudentService() {
return new StudentServiceImpl();
}
}
<bean id="studentService" class="springInit.serviceFactory"/>
@Test
public void test() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
serviceFactory bean = (serviceFactory)context.getBean("studentService");
bean.getStudentService().some();
}
使用spring的动态工厂bean
spring对于使用动态工厂所创建的bean,有专门的属性定义。factory-bean指定相应的工厂bean,由factory-method指定创建所用的方法。配置文件需要注册工厂bean和目标bean,而测试类不需要获取工厂bean,直接获取目标bean即可。
<bean id="factory" class="springInit.serviceFactory"/>
<bean id="serviceStudent" factory-bean="factory" factory-method="getStudentService"/>
@Test
public void test2() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
StudentServiceImpl bean = (StudentServiceImpl)context.getBean("serviceStudent");
bean.some();
}
静态工厂bean
静态工厂不再需要工厂实例,因此不需要静态工厂bean。对于目标bean,其不是由自己的类创建的,所以无需指定自己的类,但其是工厂类创建的,所以需要指定工厂类和工厂方法
public static IStudentService getStudentService() {
return new StudentServiceImpl();
}
<bean id="serviceStudent" class="springInit.serviceFactory" factory-method="getStudentService"/>
Bean的作用域
bean可以指定scope属性,为bean指定作用域。
1.singleton:单态模式。即在整个spring容器中,使用singleton定义的bean是单例的,默认为单态。
2.prototype:原型模式。即每次调用getbean获取的bean实例都是一个新的实例
3.request:每次http请求,都会产生一个新的bean实例
4.session:对于不同的session,都会产生一个新的bean实例
Bean后处理器
Bean后处理器是一个特殊的bean,容器中所有的bean在初始化时,均会自动执行该类的两个方法,能够实现对指定bean中指定方法进行增强。Bean后处理器注册时无需id,系统自动调用。
代码中需要自定义bean后处理器类,其实是实现BeanPostProcessor的类。该接口中包含两个方法,分别在目标bean的初始化前和初始化后执行,返回值为:被增强后的bean。
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
return null;
}
public class MyBeanPostProcessor implements BeanPostProcessor{
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("serviceStudent".equals(beanName)) {
Object proxy=Proxy.newProxyInstance(bean.getClass().getClassLoader(),bean.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("some".equals(method.getName())) {
//执行目标方法
Object result=method.invoke(bean, args);
System.out.println("some()增强");
return result;
}
return method.invoke(bean,args);
}
} );
return proxy;
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// TODO Auto-generated method stub
return bean;
}
}
配置文件
<bean id="serviceStudent" class="springInit.StudentServiceImpl"/>
<bean class="springInit.MyBeanPostProcessor"/>
测试类
@Test
public void test001() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//注意:不能用接口的实现类来转换动态代理的实现类,应该使用共同的接口来转换。
IStudentService bean = (IStudentService)context.getBean("serviceStudent");
bean.some();
}
Bean的生命周期
- 调用无参构造器,创建实例对象
- 调用参数的setter,为属性注入值
- 若bean类实现了BeanNameAware接口,则会执行接口方法setBeanName(String beanId),使bean类可以获取其在容器中的id名称。
- 若bean类实现了BeanFactoryAware接口,则执行setBeanFactory(BeanFactory factory),使bean可以获取BeanFactory对象
- 若定义并注册了bean后处理器,则执行接口方法postProcessBeforeInitialization()方法
- 若bean实现了InitializingBean接口,则执行接口方法afterPropertiesSet()方法。该方法在bean的所有属性的set方法执行完毕后执行,是bean初始化结束的标志,即bean实例化结束。
- 若设置了init-method,则执行
- 若定义并注册了bean后处理器,则执行接口方法postProcessAfterInitialization()方法
- 执行业务方法
- 若bean实现了DisposableBean接口,则执行接口destory()
- 若设置了destory-method方法,则执行