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

   

相关内容

热门资讯

魔兽世界奥格瑞玛地下的洞穴在哪... 魔兽世界奥格瑞玛地下的洞穴在哪?发图!谢谢怒焰峡谷,再暗巷区,很容易找到地图上被标记的位置.知道奥格...
动漫人物特殊眼睛 动漫人物特殊眼睛两仪式、远野志贵——直死之魔眼爱尔奎特——或链魅惑之眼日向迟码家族——白眼宇智波家族...
魏晋士大夫为何爱上茶?最初如何... 魏晋士大夫为何爱上茶?最初如何吃茶地清火去燥,芳香营养。
搜索一下米兰昆德拉 搜索一下米兰昆德拉是出自《慢》
暴饮暴食的危害有哪些? 暴饮暴食的危害有哪些?暴饮暴食是一种不好的生活习惯,所带来的危害有以下,第一点就是可能会导致胃肠道溃...
怎样锻炼胸肌、腹肌、臂部肌肉及... 怎样锻炼胸肌、腹肌、臂部肌肉及力量?我是高二的学生(学舞蹈的),只能睡前锻炼一会儿!大约15分钟,没...
煮莲子时为什么会有很多泡沫? 煮莲子时为什么会有很多泡沫?煮莲子时为什么会有很多泡沫?如果是单独的莲子不会出现泡沫的。市场上的莲子...
韩语哈哈怎么写 韩语哈哈怎么写哈哈:하하(haha)하하,但是现在都简写成ㅎㅎ하 하 哈哈허허 呵呵ㅋㅋ 呵呵
粗粮豆包的做法 粗粮豆包的做法粗粮豆包首先要把发面发好,把出粮也放进一起发。发好以后的面,然后把豆子蒸熟以后给它搅碎...
抬头仰望夜空, 月亮旁边一颗很... 抬头仰望夜空, 月亮旁边一颗很明亮的星星是什么名字?启明星啊!我都知!系金星啊,启明星一般系日出前出...
什么是节拍?怎么区分? 什么是节拍?怎么区分?我正在学吉他!小学音乐没有学好。节拍就是用分数表示的那个东东啦!比如2/4、3...
我的偶像妈妈(有着独特的精神令... 我的偶像妈妈(有着独特的精神令我佩服)比如:乐于助人,无私奉献,拾金不昧等在我们的身边,有很多值得敬...
在学校吃早点作文 在学校吃早点作文每次的清晨,总是妈妈在天还没亮透的时候起床,给我做早餐。  按理说,我是一个很幸福的...
燕雀处堂什么意思? 燕雀处堂什么意思? 意思是燕雀住在堂上,比喻生活安定而失去警惕性,也比喻大祸临头而自己不知道。燕雀处...
有什么释放压力的游戏 有什么释放压力的游戏人多的游戏,会玩的很开心,还有自己感兴趣的
帮忙评价一下我的文章,从主题;... 帮忙评价一下我的文章,从主题;脉络;详略;语言来评价(每点简单写一两句就好了)顺便评个分,满分60帮...
形容人老实。本分。善良,的成语... 形容人老实。本分。善良,的成语。多多益善?表示善良的成语:善良设身处地于心何忍安分规行矩步浑俗和光既...
妈咪爱:宝宝便秘那些事儿,妈妈... 妈咪爱:宝宝便秘那些事儿,妈妈们造吗秋天到了,早晚温差大,天气越来越干燥,宝宝体内容易产生火气,小便...
韩语分为多少个等级 韩语分为多少个等级现在TOPIK分为两个等级TOPIK I、TOPIK II,各等级又可细分为:TO...
黑暗荣耀结局是什么? 黑暗荣耀结局是什么? 黑暗荣耀周汝正准备为父报仇。《黑暗荣耀》中男主周汝正经历了父亲被杀后,杀死父亲...