1,从 Spring 2.5 开始就可以使用注解来配置依赖注入
2,关键字<context:annotation-config/>
注解 | 描述 |
---|---|
@Required | 注解应用于 bean 属性的 set 方法 |
@Autowired | 注解可以应用到 bean 属性的 set 方法、非 setter 方法、构造函数、属性 |
@Qualifier | 通过指定确切的将被连线的 bean,@Autowired 和 @Qualifier 注解可以用来删除混乱 |
JSR-250 Annotations | Spring 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。 |
@Required
应用于 bean 属性的 set 方法,在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常
它的作用相当于byName
public class Student {
private Integer age;
private String name;
@Required
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
@Required
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
如果只配置了name而没有配置age的话,将会引起BeanInitializationException异常,因为有@Required注解的方法必须在bean中配置指明
<context:annotation-config/>
<bean id="student" class="com.xxx.xxx.Student">
<property name="name" value="test1" />
<property name="age" value="11"/>
</bean>
@Autowired
对在哪里和如何完成自动连接提供了更多的细微的控制
如果在set方法上使用@Autowired ,那么它的作用相当于byType
import org.springframework.beans.factory.annotation.Autowired;
public class Tes1t{
private Test2 test2;
@Autowired
public void setTest2 ( Test2 test2){
this.test2= test2;
}
public Test2 getTest2 ( ) {
return test2;
}
}
<context:annotation-config/>
<bean id="test1" class="com.xxx.xxx.Test1"/>
<bean id="test2" class="com.xxx.xxx.Test2"/>
@Autowired也可以直接配置在属性上,这样做相当于赋值于set方法
import org.springframework.beans.factory.annotation.Autowired;
public class Tes1t{
@Autowired
private Test2 test2;
public Test2 getTest2 ( ) {
return test2;
}
}
@Autowired也可以直接配置在构造方法上,这样做当这个类被创建的时候,就会set进构造方法所需要的参数
import org.springframework.beans.factory.annotation.Autowired;
public class Tes1t{
private Test2 test2;
@Autowired
public Tes1t( Test2 test2){
this.test2= test2;
}
public Test2 getTest2 ( ) {
return test2;
}
}
@Autowired 的(required=false)选项
默认情况下是true,类似于@Required,参数是必须传递的。
false的话,则参数可以不传递
@Qualifier 注释
当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱
public class Student {
private Integer age;
private String name;
public void setAge(Integer age) {
this.age = age;
}
public Integer getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Profile {
@Autowired
@Qualifier("student1")
private Student student;
public Profile(){
System.out.println("Inside Profile constructor." );
}
public void printAge() {
System.out.println("Age : " + student.getAge() );
}
public void printName() {
System.out.println("Name : " + student.getName() );
}
}
我们的bean中有两个student,我们可以使用Qualifier来指定我们需要的是student1还是student2
<context:annotation-config/>
<bean id="profile" class="com.xxx.xxx.Profile">
</bean>
<bean id="student1" class="com.xxx.xxx.Student">
<property name="name" value="test1" />
<property name="age" value="11"/>
</bean>
<bean id="student2" class="com.xxx.xxx.Student">
<property name="name" value="test2" />
<property name="age" value="2"/>
</bean>
JSR-250 注释
它包括 @PostConstruct, @PreDestroy 和 @Resource 注释
@PostConstruct 和 @PreDestroy 注释:
定义你的bean的生命周期
@Resource 注释:
相当于byName
public class Test{
private Test2 test2;
@Resource(name= "testTwo")
public void setMessage(Test2 test2){
this.test2= test2;
}
public Test2 getTest2 (){
return test2;
}
@PostConstruct
public void init(){
System.out.println("Bean is going through init.");
}
@PreDestroy
public void destroy(){
System.out.println("Bean will destroy now.");
}
}
<context:annotation-config/>
<bean id="test" class="com.xxx.xxx.Test" init-method="init" destroy-method="destroy">
</bean>
<bean id="testTwo" class="com.xxx.xxx.TestTwo"/>
基于 Java 的配置
@Configuration
带有 @Configuration 的注解类表示这个类可以使用 Spring IoC 容器作为 bean 定义的来源
@Bean
@Bean 注解告诉 Spring,一个带有 @Bean 的注解方法将返回一个对象,该对象应该被注册为在 Spring 应用程序上下文中的 bean
import org.springframework.context.annotation.*;
@Configuration
public class Test{
@Bean
public Test2 test2(){
return new Test2();
}
}
上面的代码将等同于下面的 XML 配置:
<beans>
<bean id="test2" class="com.xxx.xxx.Test2" />
</beans>
解析
ApplicationContext ctx =
new AnnotationConfigApplicationContext(Test.class);
可以加载各种配置类
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();
Test test = ctx.getBean(Test.class);
@Import
允许从另一个配置类中加载 @Bean 定义
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B a() {
return new A();
}
}
当实例化上下文时,不需要同时指定 ConfigA.class 和 ConfigB.class,只需要 ConfigB 类
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(ConfigB.class);
A a = ctx.getBean(A.class);
B b = ctx.getBean(B.class);
}
生命周期回调
public class Foo {
public void init() {
// initialization logic
}
public void destroy() {
// destruction logic
}
}
@Configuration
public class AppConfig {
@Bean(initMethod = "init", destroyMethod = "destroy" )
public Foo foo() {
return new Foo();
}
}
@Scope 指定 Bean 的范围
默认范围是单实例
@Configuration
public class AppConfig {
@Bean
@Scope("prototype")
public Foo foo() {
return new Foo();
}
}
事件处理
Spring 内置事件 | 描述 |
---|---|
ContextRefreshedEvent | 当使用 ConfigurableApplicationContext 接口的 refresh() 方法刷新。ApplicationContext 被初始化或刷新时,该事件也会被发布。 |
ContextStartedEvent | 当使用 ConfigurableApplicationContext 接口中的 start() 方法开始 |
ContextStoppedEvent | 当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 |
ContextClosedEvent | 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 |
RequestHandledEvent | 这是一个 web-specific 事件,告诉所有 bean, HTTP 请求已经被服务。 |
监听上下文事件
一个 bean 应该实现只有一个方法 onApplicationEvent() 的 ApplicationListener 接口
public class Test{
private String message;
public void setMessage(String message){
this.message = message;
}
public void getMessage(){
System.out.println("Your Message : " + message);
}
}
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStartedEvent;
public class CStartEventHandler
implements ApplicationListener<ContextStartedEvent>{
public void onApplicationEvent(ContextStartedEvent event) {
System.out.println("ContextStartedEvent Received");
}
}
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextStoppedEvent;
public class CStopEventHandler
implements ApplicationListener<ContextStoppedEvent>{
public void onApplicationEvent(ContextStoppedEvent event) {
System.out.println("ContextStoppedEvent Received");
}
}
<bean id="test" class="com.xxx.xxx.Test">
<property name="message" value="Hello World!"/>
</bean>
<bean id="cStartEventHandler"
class="com.xxx.xxx.CStartEventHandler"/>
<bean id="cStopEventHandler"
class="com.xxx.xxx.CStopEventHandler"/>
public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
context.start();
Testobj = (Test) context.getBean("test");
obj.getMessage();
context.stop();
}
自定义事件
import org.springframework.context.ApplicationEvent;
public class CustomEvent extends ApplicationEvent{
public CustomEvent(Object source) {
super(source);
}
public String toString(){
return "My Custom Event";
}
}
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
public class CustomEventPublisher
implements ApplicationEventPublisherAware {
private ApplicationEventPublisher publisher;
public void setApplicationEventPublisher
(ApplicationEventPublisher publisher){
this.publisher = publisher;
}
public void publish() {
CustomEvent ce = new CustomEvent(this);
publisher.publishEvent(ce);
}
}
import org.springframework.context.ApplicationListener;
public class CustomEventHandler
implements ApplicationListener<CustomEvent>{
public void onApplicationEvent(CustomEvent event) {
System.out.println(event.toString());
}
}
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ConfigurableApplicationContext context =
new ClassPathXmlApplicationContext("Beans.xml");
CustomEventPublisher cvp =
(CustomEventPublisher) context.getBean("customEventPublisher");
cvp.publish();
cvp.publish();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="customEventHandler"
class="com.xxx.xxx.CustomEventHandler"/>
<bean id="customEventPublisher"
class="com.xxx.xxx.CustomEventPublisher"/>
</beans>