为什么要使用直接配置?
当然是便捷性,维护性强呀~
如果想要使用注解,在XML文件中需要什么配置?
##注解配置载入
四个重要的注解
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
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注释
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的配置
重要的辅助注解
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事件
如何处理事件?
标准事件
注意: 由于 Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。
监听上下文事件
如何实现? bean实现ApplicationListener
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、自定义事件
如何定义事件?
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