spring-ioc-2
1.Bean生命周期回调--->并非springBean的生命周期
(1)初始化回调
1.bean实现org.springframework.beans.factory.InitializingBean接口
重写void afterPropertiesSet() throws Exception;
官方不建议使用!!!,推荐使用注解
原因:我们建议您不要使用该InitializingBean
接口,因为它会不必要地将代码耦合到Spring。或者,我们建议使用@PostConstruct
注释或指定POJO初始化方法
2.annotation方式---jsr的注解非spring提供的
@PostConstruct
3.xml配置
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean { public void init() { // do some initialization work } }
(2)销毁回调-->Destruction Callbacks
1.bean实现org.springframework.beans.factory.DisposableBean接口,重写
void destroy() throws Exception;
方法官方不推荐使用!!!!
原因:同上
2.使用annotation
@PreDestroy
3.xml配置
<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean { public void cleanup() { // do some destruction work (like releasing pooled connections) } }
(3)定义默认的初始化和销毁的方法
pojo:
public class DefaultBlogService implements BlogService { private BlogDao blogDao; public void setBlogDao(BlogDao blogDao) { this.blogDao = blogDao; } // 名字任意,xml文件作出相应的声明即可 public void init() { if (this.blogDao == null) { throw new IllegalStateException("The [blogDao] property must be set."); } } /* public void destory() { //...... } */ }
config.xml:
<beans default-init-method="init"> <!-- default-destroy-method=" destory " --> <bean id="blogService" class="com.something.DefaultBlogService"> <property name="blogDao" ref="blogDao" /> </bean> </beans>
2.ApplicationContextAware
和BeanNameAware
(1)ApplicationContextAware
用途:
对其他bean进行编程检索。有时这种能力很有用。但是,一般情况下,您应该避免使用它,因为它将代码耦合到Spring并且不遵循Inversion of Control样式,其中协作者作为属性提供给bean。其他方法 ApplicationContext
提供对文件资源的访问,发布应用程序事件和访问MessageSource
。这些附加功能在附加ApplicationContext
功能中描述 。
接口定义:
public interface ApplicationContextAware { void setApplicationContext(ApplicationContext applicationContext) throws BeansException; }
应用场景:参考https://www.cnblogs.com/cg961107/p/11225325.html
官方不推荐使用
(2)BeanNameAware
用途:
在spring对实现该接口的bean初始化时调用该方法,name为bean的名称
接口定义:
public interface BeanNameAware { void setBeanName(String name) throws BeansException; }
应用实例:
@Service public class IndexServiceImpl implements IndexService,BeanNameAware { @Autowired private IndexDao indexDao; @Override public void get() { indexDao.get(); } @Override public void setBeanName(String name) { System.out.println("bean的名字为-->"+name); } }
console:
bean的名字为-->indexServiceImpl
3.基于注释的spring配置
1.@Configuration:表示该类为spring的初始化类---->applicationContext.xml
@bean------><bean id="methodName" Class="方法返回值"></bean>
@Configuration public class MovieConfiguration { @Bean public MovieCatalog firstMovieCatalog() { ... } @Bean public MovieCatalog secondMovieCatalog() { ... } // ... }
2.@primary---->表示当多个bean可以自动装配到单值依赖项时,应该优先选择特定的bean。
使用场景:当我通过AnnotationConfigApplicationContext.getBean一般通过两种形式,byName,byType
当时通过byType时,程序会抛异常,因为两个MovieCatalog,name可以通过@primary去指定优先选择哪个Bean
@Bean @Primary public MovieCatalog firstMovieCatalog() { ... }
xml方式则为:
<bean class="example.SimpleMovieCatalog" primary="true"> <!-- inject any dependencies required by this bean --> </bean>
3.@Qualifier
上文已经总结.
4.Environment Abstraction 环境抽象
两种声明方式
类
@Configuration @Profile("development") public class StandaloneDataConfig { @Bean public DataSource dataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.HSQL) .addScript("classpath:com/bank/config/sql/schema.sql") .addScript("classpath:com/bank/config/sql/test-data.sql") .build(); } }
配置类中的方法:
@Configuration public class AppConfig { @Bean("dataSource") @Profile("development") public DataSource standaloneDataSource() { return new EmbeddedDatabaseBuilder() .setType(EmbeddedDatabaseType.HSQL) .addScript("classpath:com/bank/config/sql/schema.sql") .addScript("classpath:com/bank/config/sql/test-data.sql") .build(); } @Bean("dataSource") @Profile("production") public DataSource jndiDataSource() throws Exception { Context ctx = new InitialContext(); return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); } }
作用:比如说,我们有两个数据源,一个用于生产,一个用于测试,那么我可以通过@Profile声明其所在环境,使spring去加载指定的bean,那么如何使用呢
举例:
配置类:
一个生产,一个测试
@Configuration @ComponentScan("cn.cg.*") public class AppConfig { @Bean @Profile("test") public Person person1(){ Person p = new Person(); p.setName("张三"); return p; } @Bean() @Profile("produce") public Person person2(){ Person p = new Person(); p.setName("李四"); return p; } }
test:
public class mainClass { public static void main(String[] args) { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(); //设置环境抽象 ac.getEnvironment().setActiveProfiles("produce"); //注册appConfig ac.register(AppConfig.class); //刷新容器 ac.refresh(); //获取 person->李四 Person person = ac.getBean(Person.class); System.out.println(person.getName()); } }
console:李四