Spring--IOC注解方式注入
2020-12-18 04:35
标签:config session throw 执行 lifecycle 输出 etl 个人 ica Spring实现IOC注入的方式有 第一步:@Configuration配置一个上下文环境,并在里面使用@Bean注解返回需要注入的对象,指定beanId 第二部:根据beanId获取需要的实例对象 如果有很多bean要注入,那么要写很多@Bean注解吗,这里有更方便的写法 在需要注入的类上添加@Component注解,并设置beanId 通过方法注入Bean 实际需求中,我们可能需要每次返回的对象是同一个,也可能每次创建不同的实例对象,也可能根据不同的场景,比如不同请求,不同会话等返回不同实例,这就涉及到Bean的作用域。 根据日志可以看出,默认scope为singleton,prototype就是每次调用都是创建新的实例,但是默认单例创建的实例和添加单例注解创建的实例不是一样的。 默认创建实例是在获取上下文的同时进行创建,但是特殊要求也可以满足在需要Bean的时候才创建,这就涉及到Bean的懒加载 看下输出日志 在看下去掉懒加载后的日志输出 可以看出去掉懒加载后也就是默认模式是在初始化上下文的时候呀直接创建了实例对象 实际场景中,我们需要监听IOC容器中,Bean的生命周期,有三种方法可以实现。 我们看到,销毁的方法并没有执行,因为上下文没有销毁,我们尝试把当前的上下文关闭,把 这样,销毁方法也调用了,可见Bean的销毁是由上下文的销毁触发的。 同样,自定义的方法也正常执行了 以上内容包含了IOC容器注解方式注入的大部分功能,这是基于Spring方式,如果是Spring Boot方式,还有更加简单,请听下回分解。 Spring--IOC注解方式注入 标签:config session throw 执行 lifecycle 输出 etl 个人 ica 原文地址:https://www.cnblogs.com/KingJA/p/14094008.htmlxml
和注解
两种方式,异曲同工,这里我们讲述注解方式,因为这也是一种趋势,主要优点实现简便,代码可读性强(个人理解)。
注解方式实现IOC注入,主要涉及以下几个注解
注解方式实现的一个简单的案例
@Configuration
public class BeanConfiguration {
//将一个bean交由spring创建并管理
@Bean(value = "bean1")
public Bean1 getBean1() {
return new Bean1();
}
}
public class IoCAnnotationTest {
@Test
public void test() {
//获取Spring上下文
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
//获取bean
// Bean1 bean1 = (Bean1) context.getBean("getBean1");//beanId默认为方法名
Bean1 bean1 = (Bean1) context.getBean("bean1");//通过@Bean value属性设置beanId
System.out.println(bean1);
}
}
//创建一个class配置文件
@Configuration
//扫描指定包下的所有带@Component的bean,交由Spring管理
@ComponentScan(value = "com.kingja.iocannotation.bean")
public class BeanScanConfiguration {
}
//通过value设置beanId
@Component(value = "bean2")
//默认beanId是类名(首字母小写bean2)
public class Bean2 {
}
注入Bean的几种方式
通过构造方法注入
@Component
public class OutterBean {
private InnerBean innerBean;
@Autowired
public OutterBean(InnerBean innerBean) {
this.innerBean = innerBean;
}
}
通过setter方法注入
@Autowired
public void setInnerBean2(InnerBean innerBean2) {
this.innerBean2 = innerBean2;
}
通过属性注入
@Component
public class OutterBean {
@Autowired
private InnerBean innerBean3;
注入集合
/**
* 1.寻找所有统一泛型的集合,方法名符合参数名的集合进行注入
* 2.寻找所有类型为泛型类型,组合成集合然后进行注入
* 3.如果需要精确注入,则用@Qualifier("myStringList")进行制定beanId
* 方式2优先于方式1
* 将会在容器里寻找List
@Configuration
//扫描指定包下的所有带@Component的bean,交由Spring管理
@ComponentScan(value = "com.kingja.iocannotation.bean")
public class BeanScanConfiguration {
@Bean("myStringList")
public List
注入普通字段
@Component
public class OutterBean {
private String stringValue;
private Integer intValue;
@Value("666")
public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}
/**
* @Value将字符串直接转成整型进行注入
*/
@Value("999")
public void setIntValue(Integer intValue) {
this.intValue = intValue;
}
注入直接可用的接口
@Component
public class OutterBean {
private ApplicationContext applicationContext;
@Autowired
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
IOC的作用域
Bean的作用域主要包含以下几种:
通过测试我们来检验singleton和prototype两种作用域@Configuration
public class BeanScopeConfiguration {
@Bean(value = "defaultBean")
public Bean1 getDefaultBean() {
return new Bean1();
}
@Bean(value = "singletonBean")
@Scope(value = "singleton")
public Bean1 getSingletonBean() {
return new Bean1();
}
@Bean(value = "prototypeBean")
@Scope(value = "prototype")
public Bean1 getPrototypeBean() {
return new Bean1();
}
}
@Test
public void testScope() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanScopeConfiguration.class);
Bean1 defaultBean1 = (Bean1) context.getBean("defaultBean");
Bean1 defaultBean2 = (Bean1) context.getBean("defaultBean");
System.out.println("defaultBean1 : "+defaultBean1);
System.out.println("defaultBean2 : "+defaultBean2);
Bean1 singletonBean1 = (Bean1) context.getBean("singletonBean");
Bean1 singletonBean2 = (Bean1) context.getBean("singletonBean");
System.out.println("singletonBean1 : "+singletonBean1);
System.out.println("singletonBean1 : "+singletonBean2);
Bean1 prototypeBean1 = (Bean1) context.getBean("prototypeBean");
Bean1 prototypeBean2 = (Bean1) context.getBean("prototypeBean");
System.out.println("prototypeBean1 : "+prototypeBean1);
System.out.println("prototypeBean2 : "+prototypeBean2);
}
defaultBean1 : com.kingja.iocannotation.bean.Bean1@70cf32e3
defaultBean2 : com.kingja.iocannotation.bean.Bean1@70cf32e3
singletonBean1 : com.kingja.iocannotation.bean.Bean1@5a59ca5e
singletonBean1 : com.kingja.iocannotation.bean.Bean1@5a59ca5e
prototypeBean1 : com.kingja.iocannotation.bean.Bean1@4d1bf319
prototypeBean2 : com.kingja.iocannotation.bean.Bean1@6f53b8a
@Lazy 懒加载
@Lazy可以和以下几种注解进行配合使用:
@Configuration
//@Lazy //全局配置懒加载
public class BeanLazyConfiguration {
@Bean(value = "lazyBean")
@Lazy
public Bean1 getLazyBean() {
return new Bean1();
}
}
public class Bean1 {
public Bean1() {
System.out.println("Bean1 init");
}
}
@Test
public void testLazy() {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanLazyConfiguration.class);
System.out.println("context init");
Bean1 bean = (Bean1) context.getBean("lazyBean");
System.out.println(bean);
}
context init
Bean1 init
com.kingja.iocannotation.bean.Bean1@3e08ff24
@Bean(value = "lazyBean")
// @Lazy
public Bean1 getLazyBean() {
return new Bean1();
}
Bean1 init
context init
com.kingja.iocannotation.bean.Bean1@7c137fd5
bean的初始化和销毁
方法一:实现InitializingBean, DisposableBean接口@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("destroy");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet");
}
}
afterPropertiesSet
com.kingja.iocannotation.bean.LifecycleBean@183ec003
AnnotationConfigApplicationContext 换成AbstractApplicationContext,并调用close()。
@Test
public void testLifecycle() {
// AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(CommonBeanConfiguration.class);
AbstractApplicationContext context =new AnnotationConfigApplicationContext(CommonBeanConfiguration.class);
LifecycleBean bean = (LifecycleBean) context.getBean("lifecycleBean");
System.out.println(bean);
context.close();
}
afterPropertiesSet
com.kingja.iocannotation.bean.LifecycleBean@183ec003
destroy
方法二:Bean类上设置@PostConstruct和@PreDestory注解,自定义初始化和销毁方法@PostConstruct
public void onInit() throws Exception {
System.out.println("onInit");
}
@PreDestroy
public void onDestory() throws Exception {
System.out.println("onDestory");
}
onInit
afterPropertiesSet
com.kingja.iocannotation.bean.LifecycleBean@1fe20588
onDestory
destroy
方法二:
设置@Bean的initMethod和destroyMethod属性@Bean(value = "lifecycleBean" ,initMethod = "onInitByAnnotation",destroyMethod = "onDestoryByAnnotation")
public LifecycleBean getLifecycleBean() {
return new LifecycleBean();
}
onInit
afterPropertiesSet
onInitByAnnotation
com.kingja.iocannotation.bean.LifecycleBean@6973bf95
onDestory
destroy
onDestoryByAnnotation
同样也正常执行了
总结