Spring Framework笔记(二)
2016-07-13 06:43
525 查看
IoC容器
IoC也就是DI,其实是规定了当前对象A所依赖的对象B必须要通过以下方式传入A:A构造函数的参数
指向A的工厂方法参数
A的属性文件
上述过程之所以叫做反转控制,是因为A可以控制它的依赖对象B的实例化。在spring-bean和spring-context里面有BeanFactory和它的子接口ApplicationContext来实现反转控制。
一个重要的概念叫做bean,bean指的是被Spring IoC容器管理的开发者应用中的核心部分。如果bean没有被IoC容器控制,那么它就是一个简单的对象。
容器简介
ApplicationContext就代表了Spring的IoC容器。它负责根据configuration metadata实例化,配置,组装一系列bean。Configuration metadata其实就是XML文件/Java注解/Java代码用来告诉IoC容器你所制定的规则。简单的讲,
System=Container(Metadata+POJOs)
为了告诉容器一个类是一个bean,我们可以在XML里面定义标签bean或者在java里面@Configuration注解的类里面用@Bean注解相应的类方法。通常需要定义的bean包括service layer object,data access object,presentation object, infrastructure object等等。
实例化容器可以通过ClassPathXmlApplicationContext来导入相应的XML文件。如果需要在程序中读取bean的实例,可以通过context.getBean()得到。但是,如果你需要getBean,那你的应用就会对Spring API产生依赖,我们不希望这种依赖发生。
Bean简介
bean的定义存在于BeanDefinition对象里面,包含了实现bean的类名,bean的动作类配置(scope, lifecyle callbacks, etc.),所依赖的类,其它配置。Spring支持通过ApplicationContext的getBeanFactory()来得到DefaultListableBeanFactory(),然后可以registerSingleton()和registerBeanDefinition()来加入外部bean。对于metadata和singleton的实例,它们应该被尽早的注册以使得autowire可以使用。runtime注册bean是不支持的。
依赖
依赖可以有两种方式注入,通过constructor和setter两种方式:constructor注入类似于直接在bean的构造函数里面指明如何去做。比较适合mandatory dependencies。推荐使用,因为不会产生dependencies是null的情况。
setter注入类似通过工厂类方法告诉bean需要创建这么一个对象。一般用于optional dependencies。可以通过加@Required注解变成required dependency。
dependency解析过程如下(类比Java object的new过程):
容器load: ApplicationContext被初始化(configuration metadata)
创建bean: 对每一个bean,它们的dependencies会在bean创建的时候提供,创建bean的property或者constructor argument会被加入
在XML配置文件中,可以用p-namespace来替代property标签:
<bean name="classic" class="com.example.Person"> <property name="name" value="John"/> <property name="spouse" ref="Jane"/> </bean> <bean name="p-namespace" class="com.example.Person" p:name="John" p:spouse-ref="Jane"/>
同样的,constructor-arg也可以用c-namespace来替代。
注入方法通常发生在一个singleton bean需要调用非singleton bean的时候。为了处理这种问题,可以让singleton bean利用ApplicationContextAware接口来通知容器去实例化非singleton bean。
Bean作用范围
singleton (默认):容器仅仅创建一个实例,并将其放在用来存放singleton bean的cache里面。(适用于无状态bean)prototype:一个bean class对应多个实例,需要的时候由容器实例化。(适用于有状态bean)Spring负责prototype bean的实例化,配置,组装,交给客户。因此,清理bean的实例将由客户完成,或者,需要bean的post-processor来清理。这点类似于Java的new,但是没有delete。
request, session, globalSession, application, websocket:这些都是web应用的scope。如果使用Spring MVC,那么DispatcherServlet将会自动处理bean的范围。如果request不在DispatcherServlet范围内,那么可以考虑RequestContextListener和RequestContextFilter。
对于这些范围型bean,如果short-lived bean要被注入到long-lived bean,那么我们需要利用aop:scoped-proxy来完成。简单的讲,如果一个session-scope bean要被注入到singleton bean或者application-scope bean,在不使用proxy的情况下,session-scope bean其实一直是singleton bean初始化时候的被初始化的bean。加入了proxy就意味着proxy会去获取session-scope bean对应于当前session的实例。
bean的生命周期管理
当一个bean在生命周期开始和结束的时候,我们可以选择加入做一些自定义的code。这个可以通过容器的@PostConstruct / init-method和@PreDestroy / destroy-method方法来实现。有时候,你不得不使用SmartLifecycle来自定义bean的shutdown方法(在非web的情况下,开发者需要保证这点)。Bean定义的继承
bean是可以被继承的,只需要在子bean里面加入父bean作为parent属性即可,另外,也可以声明父bean为abstract。这点类似于标准的Java。容器扩展点
在Spring中,可以利用BeanPostProcessor来操纵bean的实例(注意,这个processor是在实例化以后起作用的)。AOP在bean里面正是通过这种方式来放置切入点的。另外一种扩展点是利用BeanFactoryPostProcessor。和前面的processor不同的是,这里的processor可以在任何bean实例化之前读取并且更改configuration metadata。但是,如果需要更改一个已经实例化的bean,那么还是要用BeanPostProcessor。
对于FactoryBean接口,它可以用来实现容器初始化的复杂逻辑。如果需要得到FactoryBean的实例,那么,可以利用
ApplicationContext.getBean()。但是需要注意的是,参数需要加上&符号(比如,”¤tBean”),否则,得到的是currentBean的实例)。
注解配置
关于注解配置和XML配置哪种好的争论,我们暂且不谈,因为不同的开发者有不同的偏好。需要注意的是,如果在你的配置里面两者都有,那么XML注入会覆盖注解注入。@Required:对于bean的setter方法,这个注解表明了setter对应的属性必须在配置的时候读取,避免了NullPointerException。
@Autowired:可以在很多时候使用来做为依赖注入的主要方法。@Autowired,@Inject,@Resource,@Value注解是由Spring的BeanPostProcessor来实现的,所以,BeanPostProcessor和BeanFactoryProcess不能被注解。对于多重bean定义,可以利用@Primary,或者更为广泛的@Qualifier注解来定义。这样,在@Autowired注解里面,就可以选择使用。
@Resource:和@Autowired不同,@Resource可以利用bean的名字来注解,@Autowired则是利用bean的类型来注解。
@PostConstruct和@PreDestroy提供了bean生命周期的注解。
classpath扫描和管理组件
@Component用来表示一个通用的由Spring管理的组件。如果想要具体的应用, 可以利用@Repository一般标明一个组件是一个DAO,用在持久层;利用@Service来表明一个服务;利用@Controller来表明表示层。注解还可以和另外一个注解一起使用成更具体的注解。例如,@RestController = @Controller + @ResponseBody。
为了能自动检测并且注册这些组件,我们需要利用@Configuration和@ComponentScan。
JSR 330注解
@Autowired可以由@Inject来替代,@Component可以由@Named来取代。但是,功能性的比较上还是利用Spring自己的注解比较好。基于Java的容器配置
@Bean的作用就是告诉容器bean的存在,@Configuration则是用于替代传统的XML文件。为了不产生多次调用一个bean的情况,Spring建议将bean的定义放在@Configuration类里面。示例:public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.register(OtherConfig.class); ctx.refresh(); MyService mySvc = ctx.getBean(MyService.class); mySvc.doStuff(); } ==================================================== @Configuration @ComponentScan(basePackage = "com.example") public class AppConfig { @Bean(initMethod = "init", destroyMethod = "cleanup") @Scope("prototype") public MyService myService() { ... return new MyServiceImpl(); } } ==================================================== public class MyServiceImpl { public void init() { ... } public void cleanup() { ... } }
@Import可以用来导入其它的配置文件类。@Conditional用来注解
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring AOP动态代理-切面
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- Enterprise Library for .NET Framework 2.0缓存使用实例
- C# Entity Framework中的IQueryable和IQueryProvider详解
- 由vbs sort引发.NET Framework之间的关系说明
- C#修改IIS站点framework版本号的方法
- C#难点逐个击破(6):C#数据类型与.net framework数据类型
- zend framework框架中url大小写问题解决方法
- YII Framework框架教程之安全方案详解
- Yii PHP Framework实用入门教程(详细介绍)
- 微软NET Framework 3.5 Beta 1 发布 提供下载
- 使用Entity Framework(4.3.1版本)遇到的问题整理
- 模拟Spring的简单实现