标签:依赖关系 位置 信息 expected 客户 概念 调用bean tcl root
Spring框架是一个Java平台,提供全面的基础设施支持开发Java应用程序。Spring处理基础设施部分,这样你就可以专注于应用程序部分。Spring框架内,把一级对象通过设计模式封装起来,您可以放心的集成到您自己的应用程序而不用关注他们如何在后台工作。
目前,Spring框架由功能组织成大约20个模块。这些模块分为核心容器、数据访问/集成、Web,AOP(面向切面的编程)、instrument(支持和类加载器的实现来在特定的应用服务器上使用)、消息、和测试,如下列图所示。
下面是一些使用Spring框架的好处的列表:
依赖注入和控制反转是对同一件事情的不同描述,从某个方面讲,就是它们描述的角度不同。
依赖注入是从应用程序的角度在描述,可以把依赖注入描述完整点:应用程序依赖容器创建并注入它所需要的外部资源;
而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。
在Java中,依赖注入可能发生三种方法:
org.springframework.beans
和org.springframework.context
包是Spring框架IoC容器的基础。
BeanFactory
接口提供了一个高级的配置机制来管理任意属性的对象。
ApplicationContext
接口基于BeanFactory构建的
(是一个子接口)并添加其他功能,如Spring的AOP功能,信息资源处理(用于国际化)、事件传播和应用程序层的特定上下文如在web应用程序中使用WebApplicationContext
。
org.springframework.beans.factory.BeanFactory是
Spring IoC容器真是展现,负责管理上述bean。BeanFactory接口是Spring IoC容器接口的核心。
一个BeanFactory
就像包含bean集合的工厂类。BeanFactory在内部
持有多个Bean的定义,当客户端请求bean时,将bean进行实例化。
初始化时BeanFactory
能够保持对象的依赖关系。这减轻了负担从bean本身和bean客户机的配置。 BeanFactory在
一个bean的生命周期也能其作用,它可以调用bean的自定义初始化和销毁方法。
表面上看,applicationContext和BeanFactory是一样。同样加载bean定义,将bean连接在一起,分发bean。但applicationContext还提供:
三个常用的ApplicationContext实现是:
ApplicationContext context = new ClassPathXmlApplicationContext(“bean.xml”);
FileSystemXmlApplicationContext
:它从文件系统的一个XML文件加载上下文定义的。从文件系统加载应用程序上下文通过如下代码实现。
ApplicationContext context = new FileSystemXmlApplicationContext(“bean.xml”);
XmlWebApplicationContext
:它从一个web应用程序中包含的XML文件加载context。配置spring到您的应用程序有三种方式:
在Spring框架中,bean所需的依赖和服务在定义在配置文件中,配置文件通常是XML格式。通常这些配置文件都以<beans>
标签开始,含有大量的bean定义和特定于应用程序的配置选项。Spring XML配置的主要目标是让所有spring组件通过使用XML配置文件。
这意味着不会出现任何其他类型的Spring配置(如通过Java类注释或配置)。Spring XML配置中使用Spring命名空间提供的XML标记中使用的配置;Spring命名空间主要有:context、bean、jdbc、tx, aop, mvc等。
<beans> <!-- JSON Support --> <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/> <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/> <bean id="restTemplate" class="org.springframework.web.client.RestTemplate"/> </beans>
最简单的让您的应用程序加载配置文件和配置运行时组件方式是在web.xml
文件中配置DispatcherServlet,如下所示:
<web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>spring</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
在支持spring的新java配置组件中,@Configuration注解
的类和@Bean注解
的方法是核心组件。
@Bean
注解用于通过方法来实例化,配置和初始化一个新的由Spring IoC容器管理的对象。@Bean
注解和<bean/>
元素扮演相同的角色。
在一个类上使用@Configuration注解
,其主要用途是作为bean定义的来源。此外, 在同一个类中@Configuration
类允许inter-bean定义通过简单地调用实现依赖关系。最简单的@Configuration
注解类如下:
@Configuration public class AppConfig { @Bean public MyService myService() { return new MyServiceImpl(); } }
上面注解类等价于基于XML配置文件如下:
<beans> <bean id="myService" class="com.howtodoinjava.services.MyServiceImpl"/> </beans>
为了使这样的配置能生效,需要使用AnnotationConfigApplicationContext的帮助
。
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class); MyService myService = ctx.getBean(MyService.class); myService.doStuff(); }
为使组件扫描生效,只需要@Configuration
类注解如下:
@Configuration @ComponentScan(basePackages = "com.howtodoinjava") public class AppConfig { ... }
在上面的示例中com.howtodoinjava包将被扫描,寻找任何带注解@Component
的类,这些类将在容器内登记为Spring bean。
如果你使用以上的方式配置一个web应用程序,那么需要AnnotationConfigWebApplicationContext
类来使之生效。AnnotationConfigWebApplicationContext的使用可以通过配置Spring ContextLoaderListener的
servlet listener,Spring MVC DispatcherServlet
等。
<web-app> <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext --> <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </context-param> <!-- Configuration locations must consist of one or more comma- or space-delimited fully-qualified @Configuration classes. Fully-qualified packages may also be specified for component-scanning --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.howtodoinjava.AppConfig</param-value> </context-param> <!-- Bootstrap the root application context as usual using ContextLoaderListener --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Declare a Spring MVC DispatcherServlet as usual --> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext instead of the default XmlWebApplicationContext --> <init-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </init-param> <!-- Again, config locations must consist of one or more comma- or space-delimited and fully-qualified @Configuration classes --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>com.howtodoinjava.web.MvcConfig</param-value> </init-param> </servlet> <!-- map all requests for /app/* to the dispatcher servlet --> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> </web-app>
从Spring 2.5就可以使用注解来配置依赖注入。而不是使用XML来描述一个bean的注入,你可以通过使用注解相关的类,方法或字段声明将bean配置的移到注解类本身。
注释注入执行XML注入之前,因此后者配置将会覆盖前者属性连接通过这两种方法。
默认情况下,spring容器没有打开自动注解功能。所以在使用具有spring注解之前,我们需要在我们的Spring配置文件启用它。如果你想在Spring应用程序中使用的自动注解,考虑配置文件上加上下面的配置。
<beans> <context:annotation-config/> <!-- bean definitions go here --> </beans>
一旦配置了<context:annotation-config/>
,表明在Spring中您可以开始使用属性,方法和构造函数的自动注入。
一些重要的注解:
一个Spring bean的生命周期很容易理解。当一个bean实例化时可能需要执行一些初始化动作进入使bean达到一个可用的状态。同样,当不再需要bean时,将bean从容器中移除,可能需要销毁。
Spring beanFactory通过Spring容器负责管理bean的生命周期。bean的生命周期包括可以大体分类为两类的回调方法
Spring框架提供了以下四种方法控制bean的生命周期事件:
例如, customInit()
和 customDestroy()
方法生命周期方法的例子。
<beans> <bean id="demoBean" class="com.howtodoinjava.task.DemoBean" init-method="customInit" destroy-method="customDestroy"></bean> </beans>
spring容器中的bean有5中scope,分别是:
在Spring框架中,当一个bean只用于一个特定属性,建议将它声明为一个内在的bean。内部bean同时支持setter注入属性和构造函数注入“constructor-arg”。
例如,假设一个Customer
类的引用Person
类。在我们的应用程序中,我们将只创建一个Person
类的实例,并在Customer使用它。
public class Customer { private Person person; //Setters and Getters }
public class Person { private String name; private String address; private int age; //Setters and Getters }
现在内部bean声明是这样的:
<bean id="CustomerBean" class="com.howtodoinjava.common.Customer"> <property name="person"> <!-- This is inner bean --> <bean class="com.howtodoinjava.common.Person"> <property name="name" value="adminis"></property> <property name="address" value="India"></property> <property name="age" value="34"></property> </bean> </property> </bean>
Spring框架不对单例的bean做任何多线程的处理。单例的bean的并发问题和线程安全是开发人员的责任。
而实际上,大多数spring bean没有可变状态(例如服务和DAO的类),这样的话本身是线程安全的。但如果您的bean有可变状态(例如视图模型对象),这就需要你来确保线程安全。
这个问题最简单和明显的解决方案是改变bean Scope,可变的bean从“单例”到“原型”。
Spring提供了四种类型的配置元素集合,如下:
<list>:帮助注入一组值,允许重复。
<set>:帮助注入一组值,不允许重复。
< map>:帮助注入一个K-V的集合,名称和值可以是任何类型的。
<props>:帮助注入一个名称-值对集合,名称和值都是字符串。
让我们看看每种类型的例子。
<beans> <!-- Definition for javaCollection --> <bean id="javaCollection" class="com.howtodoinjava.JavaCollection"> <!-- java.util.List --> <property name="customList"> <list> <value>INDIA</value> <value>Pakistan</value> <value>USA</value> <value>UK</value> </list> </property> <!-- java.util.Set --> <property name="customSet"> <set> <value>INDIA</value> <value>Pakistan</value> <value>USA</value> <value>UK</value> </set> </property> <!-- java.util.Map --> <property name="customMap"> <map> <entry key="1" value="INDIA"/> <entry key="2" value="Pakistan"/> <entry key="3" value="USA"/> <entry key="4" value="UK"/> </map> </property> <!-- java.util.Properties --> <property name="customProperies"> <props> <prop key="admin">admin@nospam.com</prop> <prop key="support">support@nospam.com</prop> </props> </property> </bean> </beans>
第一个方法是使用<props>标记如下。
<bean id="adminUser" class="com.howtodoinjava.common.Customer"> <!-- java.util.Properties --> <property name="emails"> <props> <prop key="admin">admin@nospam.com</prop> <prop key="support">support@nospam.com</prop> </props> </property> </bean>
也可以使用“util:“名称空间创建bean的属性文件,并使用bean的setter方法注入。
<util:properties id="emails" location="classpath:com/foo/emails.properties" />
在spring框架中,在配置文件中设置bean的依赖是一个很好的办法,但spring容器也能够自动注入不同bean之间的关系。这意味着,通过检查BeanFactory的内容它可以为您的bean自动注入其他bean。
可以为每个bean指定是否自动注入,因此可以支持一些Bean支持自动注入,而一些bean不会自动注入。
下面从XML配置文件摘录了自动根据名称注入的bean。
<bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAOImpl" autowire="byName" />
除了提供的自动装配模式bean配置文件,也可以在bean类中指定自动装配使用 @Autowired
注释。
注意:在bean类使用@Autowired注解
,您必须在spring应用程序中先启用下面的注解。
<context:annotation-config />
也可以通过在配置文件使用AutowiredAnnotationBeanPostProcessor
bean来完成。
<bean class ="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
现在,当注释配置已经启用,您可以自由使用@Autowired来
自动注入bean依赖关系,以你喜欢的方式。
@Autowired public EmployeeDAOImpl ( EmployeeManager manager ) { this.manager = manager; }
在Spring有五个自动注入模式。让我们逐个讨论。
要启用@Autowired
,你必须注册AutowiredAnnotationBeanPostProcessor
,你可以用两种方式。
1. 在bean配置文件使用<context:annotation-config >
。
<beans> <context:annotation-config /> </beans>
2. 直接将AutowiredAnnotationBeanPostProcessor放到
bean配置文件。
<beans> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> </beans>
在大规模的应用程序中,IoC容器中可能会有成百上千的bean声明,以及它们之间的依赖关系通常是非常复杂的。
setter注入的缺点之一是,很难给你检查出所需的所有属性是否已经注入。
为了克服这个问题,您可以设置bean的“dependency-check”属性,可以设置四个属性的其中之一即 none, simple, objects or all (没有一个是默认选项)。
在现实生活中应用程序中,您将不会感兴趣检查所有上下文中的bean属性配置文件。而你想要检查一些特定的bean是否已设置特定的属性。在这种情况下,Spring的依赖项检查功能将不再适用,。
为了解决这个问题,您可以使用@Required
注解。在bean属性使用@Required
注解的setter方法类文件如下:
public class EmployeeFactoryBean extends AbstractFactoryBean<Object> { private String designation; public String getDesignation() { return designation; } @Required public void setDesignation(String designation) { this.designation = designation; } //more code here }
RequiredAnnotationBeanPostProcessor
是一个spring bean后置处理程序,检查@Required注解的
所有的bean属性是否已设置。使用这个bean属性检查后置处理程序,您必须注册在Spring IoC容器中。
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
如果@Required注解的任何属性
没有设置,这个bean的处理器会抛出一个BeanInitializationException
异常。
@Autowired
注解提供了更细粒度的控制,以及应该如何完成自动注入。@Autowired
注解和@Required注解
一样,可用于bean的自动注入,它可以作用于构造方法,属性或具有任意名称和/或多个参数的方法。
例如,您可以使用@Autowired
注解的setter方法来代替在XML配置文件中的<property>
元素。当Spring找到一个@Autowired
注解的方法,它尝试使用byType自动注入的方法。
您可以将@Autowired应用到
构造方法。一个构造方法使用@Autowired注解
表明,即使在XML文件没有配置bean的<constructor-arg>
元素,当创建bean时,构造方法也会自动注入。
public class TextEditor { private SpellChecker spellChecker; @Autowired public TextEditor(SpellChecker spellChecker){ System.out.println("Inside TextEditor constructor." ); this.spellChecker = spellChecker; } public void spellCheck(){ spellChecker.checkSpelling(); } }
没有构造方法参数的配置。
<beans> <context:annotation-config/> <!-- Definition for textEditor bean without constructor-arg --> <bean id="textEditor" class="com.howtodoinjava.TextEditor"> </bean> <!-- Definition for spellChecker bean --> <bean id="spellChecker" class="com.howtodoinjava.SpellChecker"> </bean> </beans>
@Qualifier限定哪个bean应该被自动注入
。当Spring无法判断出哪个bean应该被注入时,@Qualifier注解有助于消除歧义bean的自动注入。
参见下面的例子,
public class Customer { @Autowired private Person person; }
我们有两个bean定义为Person
类的实例。
<bean id="customer" class="com.howtodoinjava.common.Customer" /> <bean id="personA" class="com.howtodoinjava.common.Person" > <property name="name" value="lokesh" /> </bean> <bean id="personB" class="com.howtodoinjava.common.Person" > <property name="name" value="alex" /> </bean>
Spring 知道哪个bean应该自动注入?不。当您运行上面的例子时,抛出如下异常:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.howtodoinjava.common.Person] is defined: expected single matching bean but found 2: [personA, personB]
要解决以上问题,你需要使用@Quanlifier注解
告诉Spring 哪个bean应该被autowired的。
public class Customer { @Autowired @Qualifier("personA") private Person person; }
有以下几点明显的差异:
ObjectCurrentlyInCreationException
。所以Spring可以通过setter注入,从而解决循环依赖的问题。Spring的ApplicationContext具有代码层上
支持事件和监听器的功能。我们可以创建bean监听通过ApplicationContext发布的事件。ApplicationContext里的事件处理通过提供ApplicationEven
t类和ApplicationListener
接口来完成。所以如果一个bean实现了ApplicationListener接口
,当一个ApplicationEvent
发布到ApplicationContext时,该bean将接到
通知。
public class AllApplicationEventListener implements ApplicationListener < ApplicationEvent > { @Override public void onApplicationEvent(ApplicationEvent applicationEvent) { //process event } }
Spring提供了以下5标准事件:
ConfigurableApplicationContext
接口的refresh()方法来触发。除了上面的事件,您可以通过扩展ApplicationEvent
类创建自定义事件。如:
public class CustomApplicationEvent extends ApplicationEvent { public CustomApplicationEvent ( Object source, final String msg ) { super(source); System.out.println("Created a Custom event"); } }
监听这个事件,创建一个监听器是这样的:
public class CustomEventListener implements ApplicationListener < CustomApplicationEvent > { @Override public void onApplicationEvent(CustomApplicationEvent applicationEvent) { //handle event } }
发布这个事件:
CustomApplicationEvent customEvent = new CustomApplicationEvent( applicationContext, "Test message" ); applicationContext.publishEvent ( customEvent );
在FileSystemResource中
你需要给出spring-config.xml
(Spring配置)文件相对于您的项目的相对路径或文件的绝对位置。
在ClassPathResource中Sping
查找文件使用ClassPath,因此
spring-config.xml
应该包含在类路径下。
一句话,ClassPathResource在类路径下搜索和FileSystemResource在文件系统下搜索。
有很多不同的设计模式,但有一些明显的:
JmsTemplate
, JpaTemplate
.DispatcherServlet
,确保传入请求被分派到你的控制器。BeanFactory
/ ApplicationContext的核心
概念。标签:依赖关系 位置 信息 expected 客户 概念 调用bean tcl root
原文地址:https://www.cnblogs.com/xmlkk/p/14456027.html