Spring笔记(6):基于注解的配置
创始人
2024-05-29 09:13:54
0

为什么要使用直接配置?
当然是便捷性,维护性强呀~

如果想要使用注解,在XML文件中需要什么配置?

##注解配置载入

四个重要的注解

  • @Required: 应用于set()方法
  • @Autowired: 应用于set()方法,构造方法,属性
  • @Qualifier: 指定确切的bean
  • JSR-250 Annotations: 支持 JSR-250 的基础的注解,其中包括了 @Resource,@PostConstruct 和 @PreDestroy 注解。

1、@Required注解

Product.java

public class Product {private String pid;private String pname;public Product() {}public Product(String pid, String pname) {this.pid = pid;this.pname = pname;}public String getPid() {return pid;}@Requiredpublic void setPid(String pid) {this.pid = pid;}public String getPname() {return pname;}@Requiredpublic void setPname(String pname) {this.pname = pname;}@Overridepublic String toString() {return "Product{" +"pid='" + pid + '\'' +", pname='" + pname + '\'' +'}';}
}

Beans.xml

        

输出结果

Product{pid='p1233323', pname='经典牛奶'}

你做了以上操作,你会发现,有没有@Required都不影响你的程序运行。
为什么会出现这样的情况呢?
@Required 主要是用来标注该set()方法必须使用XML文件中显式注入,不然会报错。
它就是这个作用,但是编辑器中也会自动识别XML文件中显式注入不完整,而产生错误高亮。

2、@Autowired注解

@Autowired就是自动装配,我们在前面已经讲了自动装配适用的场景就是引用了自定义类的地方,所以该注解也同样如此,并且指明了装配该区域,使得更加效率。

@Autowired用法

例如
在字段上

    @Autowiredprivate Product product;

在set方法上

    @Autowiredpublic void setProduct(Product product) {this.product = product;}

在构造方法上

    @Autowiredpublic Sales(String sid, int price, Product product) {this.sid = sid;this.price = price;this.product = product;}

构造方法一定要在XML文件中,一定要配置好,否则会报异常。

所以我们可以意识到,Collection也同样适配@Autowired

3、@Qualifiler注解

首先理解Qualifier 的意思是 限定。
所以它的作用是限定一个bean类型进行装配

@Qualifiler通常会与@Autowired搭配使用,来限定采用哪一种同类型的bean

Sales.java

public class Sales {private String sid;private int price;@Autowired@Qualifier("product2")private Product product;public Sales(String sid, int price, Product product) {this.sid = sid;this.price = price;this.product = product;}public Sales() {}public String getSid() {return sid;}public void setSid(String sid) {this.sid = sid;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public Product getProduct() {return product;}@Autowired@Qualifier("product2")public void setProduct(Product product) {this.product = product;}@Overridepublic String toString() {return "Sales{" +"sid='" + sid + '\'' +", price=" + price +", product=" + product +'}';}
}

Beans.xml

        

输出结果

Sales{sid='sales100000', price=251, product=Product{pid='p2', pname='奥利奥'}}

4、JSR-250注释

  • @PostConstruct: 替代XML中配置init-method
  • @PreDestroy 替代XML中配置destory-method
  • @Resource 指明使用哪一个bean,如果没有指定name,则默认为字段名或setter方法。
public class Sales{@Resource(name="price")private int price;@Resource(name="product")private Product product;@Resource(name="product")public void setProduct(Product product){this.product = product;}
}

Sales.java

public class Sales implements InitializingBean, DisposableBean {private String sid;private int price;@Autowired@Qualifier("product2")private Product product;public Sales(String sid, int price, Product product) {this.sid = sid;this.price = price;this.product = product;}public Sales() {}public String getSid() {return sid;}public void setSid(String sid) {this.sid = sid;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public Product getProduct() {return product;}@Autowired@Qualifier("product2")public void setProduct(Product product) {this.product = product;}@Overridepublic String toString() {return "Sales{" +"sid='" + sid + '\'' +", price=" + price +", product=" + product +'}';}@PreDestroy@Overridepublic void destroy() throws Exception {System.out.println("Bean正在被销毁");}@PostConstructpublic void init(){System.out.println("Bean正在被初始化");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("Bean已经创建成功");}
}

输出结果

Bean正在被初始化
Bean已经创建成功
Sales{sid='sales100000', price=251, product=Product{pid='p2', pname='奥利奥'}}
Bean正在被销毁

5、基于Java的配置

重要的辅助注解

  • @Configuration: 标记为Bean定义来源
  • @Bean: 标记为注册成Spring应用程序上下文的Bean

User.java

public class User implements InitializingBean, DisposableBean {private String uid;private String uname;public User() {}public User(String uid, String uname) {this.uid = uid;this.uname = uname;}public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getUname() {return uname;}public void setUname(String uname) {this.uname = uname;}@PostConstructpublic void init(){System.out.println("Bean is going through init");}@PreDestroypublic void destroy(){System.out.println("Bean will destroy now");}@Overridepublic String toString() {return "User{" +"uid='" + uid + '\'' +", uname='" + uname + '\'' +'}';}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("UserBean has created。");}
}

UserConfig.java

@Configuration
public class UserConfig {@Beanpublic User getUser(){	//User作为class,getUser作为idreturn new User();}
}

等同于



Main.java

public class Main {public static void main(String[] args) {ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);	//通过注解配置类加载到ApplicationContext容器User user = context.getBean(User.class);	//因为配置为Bean时通过User作为id,所以需要User.class来获取对象user.setUname("我是谁呢?");System.out.println(user);}
}

输出结果

Bean is going through init
UserBean has created。
User{uid='null', uname='我是谁呢?'}

注入Bean的依赖性

跟配置XML文件相同

@Configuration
public class AppConfig{@Beanpublic Foo foo(){return new Foo(bar());}@Beanpublic Bar bar(){return new Bar();}
}

等同于




@import注解
作用: 允许集合到一个配置类中

Man.java

public class Man {private int mid;public int getMid() {return mid;}public void setMid(int mid) {this.mid = mid;}
}

Female.java

public class Female {private int fid;public int getFid() {return fid;}public void setFid(int fid) {this.fid = fid;}
}

ManConfig.java

@Configuration
public class ManConfig {@Beanpublic Man man(){return new Man();}
}

FemaleConfig.java

@Configuration
@Import(ManConfig.class)
public class FemaleConfig {@Beanpublic Female female(){return new Female();}
}

Main.java

public class Main {public static void main(String[] args) {//只需要引入最终的配置类集合,就能够通过反射机制获取对象ApplicationContext context = new AnnotationConfigApplicationContext(UserConfig.class);context = new AnnotationConfigApplicationContext(FemaleConfig.class);	Female female = context.getBean(Female.class);female.setFid(12);Man man = context.getBean(Man.class);man.setMid(23);System.out.println(female.getFid());System.out.println(man.getMid());}
}

生命周期回调

@Bean(initMethod = "init",destroyMethod = "destroy")

指定Bean的范围

@Bean
@Scope("prototype")

6、事件处理

什么是事件?

举个例子: ApplicationContext启动会有start事件,ApplicationContext结束会有stop事件

如何处理事件?

  • 工具:ApplicationEvent类和ApplicationListener接口。
  • 应用:一个bean实现ApplicationListener,则ApplicationEvent发布到ApplicationContext上时,该bean也能获取到。

标准事件

  • ContextRefreshedEvent: 初始化或刷新时,该事件被发布,也可以通过ConfigurableApplicationContext.refresh()方法发生。
  • ContextStartedEvent: 当使用ConfigurableApplicationContext.start()启动ApplicationContext时,该事件被发布,进行调查数据库或重启任何应用程序。
  • ContextStoppedEvent: 当使用ConfigurableApplicationContext.stop()暂停ApplicationContext时,该事件被发布,进行清理工作。
  • ContextClosedEvent: 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
  • RequestHandledEvent: 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。

注意: 由于 Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。

监听上下文事件
如何实现? bean实现ApplicationListener

  • 步骤1: 创建监听事件配置文件 BStartEventHandler.javaBStopEventHandler.java
  • 步骤2: 注册监听Bean Beans.xml
  • 步骤3: 获取ConfigurableApplicationContext对象 Main.java

BStartEventHandler.java

public class BStartEventHandler implements ApplicationListener {@Overridepublic void onApplicationEvent(ContextStartedEvent event) {System.out.println("the ApplicationContext Container start");}
}

BStopEventHandler.java

public class BStopEventHandler implements ApplicationListener {@Overridepublic void onApplicationEvent(ContextStoppedEvent event) {System.out.println("the ApplicationContext Container stop");}
}

Beans.xml

        

Main.java

public class Main {public static void main(String[] args) {ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");context.start();Sales sales = (Sales) context.getBean("sales");System.out.println(sales);context.stop();}
}

输出结果

Bean正在被初始化
Bean已经创建成功
the ApplicationContext Container start
Sales{sid='sales100000', price=251, product=Product{pid='p2', pname='奥利奥'}}
the ApplicationContext Container stop

7、自定义事件

如何定义事件?

  • 步骤1: 创建ApplicationEvent继承类
  • 步骤2: 创建ApplicationEventPublisherAware接口实现类
  • 步骤3: 创建监听类
  • 步骤4: 声明监听Bean
  • 步骤5: 使用发布类

CustomEvent.java

public class CustomEvent extends ApplicationEvent{ public CustomEvent(Object source) {super(source);}public String toString(){return "My Custom Event";}
}

CustomEventPublisher.java

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);	//发布事件}
}

MainApp.java

public class MainApp {public static void main(String[] args) {ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");    CustomEventPublisher cvp = (CustomEventPublisher) context.getBean("customEventPublisher");cvp.publish();}
}

Beans.xml

   

相关内容

热门资讯

屋有蜜蜂来筑巢好不好 屋有蜜蜂来筑巢好不好当然好了察祥蔽呀,蜜蜂也是风水专家,说明你家位置很好。如果不影响你们正常生活的话...
哈尔滨空调股份有限公司2025... 证券代码:600202 证券简称:哈空调 编号:临2025-036哈尔滨空调股份有限公司2025年半...
促政策与市场双轨共振,激活产业... “十四五”规划的深化布局,为中国电子信息产业绘制了波澜壮阔的发展蓝图。作为国民经济的战略性支柱产业,...
我是做电话销售的,公司安排每人... 我是做电话销售的,公司安排每人每天轮流开一次早会,谁可以给些简单的小游戏。小故事、小话术提供一下!轰...
从世运手包到童趣闯关 世运火花... 转自:成都日报锦观从世运手包到童趣闯关 世运火花在社区点燃 本报讯 (成都日报锦观新闻记者 袁...
工地开讲“护薪”课,筑牢农民工... 为切实保障农民工合法权益,7月6日,中铁上海局七公司引汉济渭项目部联合监理单位及其他标段,共同组织开...
温江区万春镇:轨道为笔 绘就公... 转自:成都日报锦观温江区万春镇:轨道为笔 绘就公园城市乡村振兴新图景 在成都建设公园城市示范...
公开通报3起整治形式主义为基层... 转自:成都日报锦观中央层面整治形式主义为基层减负专项工作机制办公室 中央纪委办公厅公开通报3起整治形...
今起三日 成都持续晴热 转自:成都日报锦观今起三日 成都持续晴热 7月20日将进入今年的“三伏天”,但在入伏前,四川...
中国石化胜利石油工程公司:以创... 在保障国家能源安全的征程中,中国石化胜利石油工程公司以一组组亮眼的数据,交出了一份沉甸甸的“半年答卷...