基于java的容器注解
@Bean标识一个用于配置和初始化一个由Spring IOC容器管理的新对象的方法,类似于XML配置文件的<bean> </bean>
可以在Spring的@Component注解的类中使用@Bean注解任何方法(仅仅是可以)
通常是使用的是@Configuration
bean的配置项可以通过注释的方式
@Bean(initMethod = "init")
@Bean(destroyMethod = "destroy")
package com.zjx.bean;
public class StringStore implements Store {
public void init(){
System.out.println("this is init...");
}
public void destroy(){
System.out.println("this is destroy");
}
package com.zjx.bean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class StoreConfig {
@Bean(initMethod="init",destroyMethod="destroy")
public Store stringStore(){
return new StringStore();
}
}
资源文件的读取方式
<context:annotation-config></context:annotation-config>
<context:property-placeholder location="classpath:/Spring/src/jdbc.properties"/>
<bean class="com.Appconfig"></bean>
<bean class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
或者在类中写注释:
package com.zjx.properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
@Configuration
@ImportResource("classpath:/Spring/src/jdbc.properties")
public class AppConfig {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String passWord;
public DataSource dataSource(){
return new DriverManagerDataSource(url, userName, passWord);
}
}
@Scope
默认@Bean是单例的
@Scope里边还有另外一个属性proxyMode,即采用哪一种的代理方式
@Bean(name = "stringStore")
//基于接口interface,基于类的TARGET_CLASS。
@Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Store stringStore() {
return new StringStore();
}
基于泛型的自动装配
@Configuration
public class MyConfiguration{
@Bean
public StringStore stringStore(){
return new StringStore();
}
@Bean
public IntegerStore integerStore(){
return new IntegerStore();
}
}
@Autowired
private Store<String> s1;
@Autowired
private Store<Integer> s2;
在进行@Autowired自动装配的时候,两个Store s1和s2,第一个是String第二个是Integer。也就是说通过这种泛型的方式来指定s1和s2分别对应哪一个bean。s1泛型里边指定的是String,那么s1对应的应该是上边的StringStore,s2对应IntegerStore。
//在一个集合里边的Store对象泛型指定的都是Integer类型的
@Autowired
private List<Store<Integer>> s;
将之前的一些类进行修改 接口里指定T泛型:public interface Store<T> {}
public class StringStore implements Store<String> {
public void init() {
System.out.println("This is init.");
}
public void destroy() {
System.out.println("This is destroy.");
}
}
public class IntegerStore implements Store<Integer> {
}
在StoreConfig类中进行声明
@Autowired
private Store<String> s1;
@Autowired
private Store<Integer> s2;
@Bean
public StringStore stringStore() {
return new StringStore();
}
@Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
@Bean(name = "stringStoreTest")
// public StringStore stringStoreTest() {
public Store stringStoreTest() {
System.out.println("s1 : " + s1.getClass().getName());
System.out.println("s2 : " + s2.getClass().getName());
return new StringStore();
}
Autowire扩展内容,关于自定义qualifier注解
CustomeAutowireConfigurer是BeanFactoryPostProcessor的子类,通过它可以注册自己的qualifier注解类型(即使没有使用Spring的@Qualifier注解)
<bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>
class指定类,这个类中有个属性customQualifierTypes,具体有哪些类型,我们可以把自己定义的类型放在里边,注意这里是Set,也就是说我们可以放很多个。
AutowireCandidateResolver
决定自动装配的候选者:
- 每个bean定义的autowire-candidate值
- 任何
<bean/>
中的default-autowire-candidates - @Qualifier注解及使用CustomAutowireConfigurer的自定义类型。
很少会使用到
对JSR的支持
@PostConstruct and @PreDestroy
CommonAnnotationBeanPostProcessor不仅能识别JSR-250中的生命周期注解@Resource,在Spring2.5中引入支持初始化回调和销毁回调,前提是CommonAnnotationBeanPostProcessor是Spring的ApplicationContext中注册的
public class CachingMovieLister{
@PostConstruct
public void populateMovieCache(){
//...
}
@PreDestroy
public void clearMovieCache(){
//...
}
}
//在初始化和销毁之前都会调用这两个注解所注解的方法。
注解提供的名字被解析成为一个bean的名称,这是由ApplicationContext中的CommonAnnotationBeanPostProcessor发现并处理的
示例:
@Repository
public class JsrDAO {
public void save() {
System.out.println("JsrDAO invoked.");
}
}
@Service
public class JsrService{
//没有DAO赋值,会出现空指针异常。
//一种是在成员变量上使用@Resource注解,还有一种是生成set方法,在这个方法上使用@Resource注解。
@Resource
private JsrDAO jsrDAO;//把DAO的实例注入到当前的实例中来
/*或
@Resource
public void setJsrDAO(JsrDAO jsrDAO) {
this.jsrDAO = jsrDAO;
}*/
public void save(){
System.out.println("JsrServie save");
jarDAO.save();
}
@PostConstruct
public void init() {
System.out.println("JsrServie init.");
}
@PreDestroy
public void destroy() {
System.out.println("JsrServie destroy.");
}
}
//单元测试
@Test
public void testSave() {
JsrServie service = getBean("jsrServie");
service.save();
}
先输出JsrServie init.,再输出save()方法调用,最后输出JsrServie destroy.
使用JSR330标准注释
从Spring3.0开始支持JSR330标准注解(依赖注入注解),其扫描方式与Spring注解一致
使用JSR330需要依赖javax.inject包
使用Maven引入方式
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1.0</version>
</dependency>
@Inject
@Inject等效于@Autowired,可以使用于类、属性、方法、构造器
import javax.inject.Inject
public class SimpleMovieLister{
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder){
this.movieFinder=movieFinder;
}
}
@Named
如果想使用特定名称进行依赖注入,使用@Named。也就是说同一种类型的bean在IOC容器中有多个的话,如果想使用特定的那个bean,就可以使用这个注解。
@Named和@Component是等效的
//注解在类上
@Named("movieListener")
public class SimpleMovieLister{
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(MovieFinder movieFinder){
this.movieFinder=movieFinder;
}
}
//用来指定某一个名称的bean。和Qualifier有点类似
public class SimpleMovieLister{
private MovieFinder movieFinder;
@Inject
public void setMovieFinder(@Named("main")MovieFinder movieFinder){
this.movieFinder=movieFinder;
}
}
在之前的例子中可以进行修改
JsrService类上的@Service可以改为Named,里边在成员变量和set方法上的@Resource注解可以改为@Inject,输出不变。
// @Resource
@Inject
public void setJsrDAO(@Named("jsrDAO") JsrDAO jsrDAO) {
this.jsrDAO = jsrDAO;
}
这里还可以加上(@Named(“jsrDAO”)。有什么作用?
加入这个JsrDAO类在当前的IOC容器中有两个bean,或者这么说,加入这是一个接口,它有两个实现类,都注入到了当前的IOC容器中,就像前边例子中的StringStore和IntegerStore,那么就可以通过Named引用到底是哪一个。
参考:
Spring入门(Spring对JSR支持的说明)
https://blog.csdn.net/qq_36206746/article/details/78141904
https://blog.csdn.net/kang82651204/article/category/6070639