github 的spring中文文档 :IOC 介绍:https://github.com/DocsHome/spring-docs/blob/master/pages/core/overview.md
IOC容器概述
ApplicationContext 是Spring IoC容器实现的代表,它负责实例化,配置和组装Bean。容器通过读取配置元数据获取有关实例化、配置和组装哪-些对象的说明 。配置元数据可以使用**XML、Java注解或Java代码**来呈现。它允许你处理应用程序的对象与其他对象之间的互相依赖关系。
使用前通过maven引入相关依赖
<!-- spring IOC 相关所有jar包入口,其中aop的包用于IOC支持注解-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
XML方式配置
用xml配置文件的方式配置bean的实例化信息。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.blog.entity.User"></bean>
</beans>
1、容器使用示例
@Test
public void test01(){
/*
* ApplicationContext对象负责实例化配置元数据。
* ClassPathXmlApplicationContext到项目路径下找配置文件。
* FileSystemXmlApplicationContext到磁盘路径获取配置文件.
* AnnotationConfigApplicationContext通过注解的方式实现对象实例化。
*
* 可以加载多个配置文件。
* */
ApplicationContext context = new ClassPathXmlApplicationContext("spring-ioc.xml", "spring-ioc2.xml");
User user = (User)context.getBean("user");
Wife wife = context.getBean(Wife.class);
System.out.println(wife);
System.out.println(user);
}
2、依赖注入
a.基于setter方法
<bean id="user" class="com.blog.entity.User"></bean>
<!-- 同一各类可以定义多个bean对象,只要id不同即可
基于setter方法的依赖注入
1、类的属性必须定义set方法
2、property中name属性解析后通过反射调用到setName()方法
3、需要保留无参的构造方法
-->
<bean id="user2" class="com.blog.entity.User">
<property name="age" value="12"></property>
<property name="name" value="小龙女"></property>
<property name="userId" value="1123"></property>
</bean>
b、基于构造方法
<!--
基于构造函数的依赖注入,定义后默认不会调用无参构造函数
1、name 对应 构造函数入参,且入参个数要一致
2、name可以省略,但是定义的参数顺序要按照构造函数的入参顺序
3、name可以用index,和type替代,index=0,代表第一个入参,但是一般不使用
-->
<bean id="user3" class="com.blog.entity.User">
<constructor-arg name="age" value="123"></constructor-arg>
<constructor-arg name="userId" value="133"></constructor-arg>
<constructor-arg name="name" value="猪八戒"></constructor-arg>
</bean>
3、不同类型的参数赋值
<bean id="user3" class="com.blog.entity.User">
<constructor-arg name="age" value="123"/>
<constructor-arg name="userId" value="133"/>
<constructor-arg name="name" value="猪八戒"/>
</bean>
<bean id="person" class="com.blog.entity.Person">
<!-- 基本类型和String类型直接赋值,包装类型也直接赋值-->
<property name="age" value="12"/>
<property name="forByte" value="127"/>
<property name="forShort" value="129"/>
<property name="forDouble" value="129946.123"/>
<property name="forFloat" value="127.0"/>
<property name="id" value="12"/>
<!--date类型赋值-->
<property name="birthday" value="2020/02/12 12:00:01"/>
<!--设置引用类型,需要引用定义好的对象的id-->
<property name="user" ref="user3"/>
<!--设置引用类型为null-->
<property name="wife">
<null/>
</property>
<!--list存放对象类型-->
<property name="childlist">
<list>
<!--相当于单独为这个list创建了一个对象,不能复用-->
<bean class="com.blog.entity.Child" id = "child1">
<property name="name" value="张飞"/>
</bean>
<ref bean="child"/>
</list>
</property>
<!--List存放string类型-->
<property name="list">
<list>
<value>元素1</value>
<value>元素2</value>
</list>
</property>
<property name="mapString">
<map>
<entry key="1" value="123"/>
<entry key="2" value="456"/>
</map>
</property>
<property name="mapObject">
<map>
<entry key="张飞" value-ref="child"/>
</map>
</property>
</bean>
<bean class="com.blog.entity.Child" id = "child">
<property name="name" value="赵云"/>
</bean>
//测试代码
@Test
public void test02(){
Person person = context.getBean("person", Person.class);
System.out.println(person);
}
4、import标签使用
可以设置一个总的springioc的xml配置文件,在其中引入其他xml配置文件,在实例化时,spring的ApplicationContext会通过总的配置文找到其他配置文件。便于不同类别的对象统一管理。比如:可以分为数据库,服务类,工具类,拦截器,过滤器等的配置文件。
<!-- 可以导入多份配置文件 -->
<import resource="spring-ioc2.xml"></import>
5、depends-on属性
<!--可以通过无参构造输出信息测试加载顺序-->
<!--depends-on可以改变bean对象的加载顺序,默认是按配置从上向下加载,配置后会先加载依赖的对象-->
<bean id="person2" class="com.blog.entity.Person" depends-on="wife">
<property name="wife" ref="wife"/>
</bean>
<bean id="wife" class="com.blog.entity.Wife"/>
6、lazy-init懒加载方式配置
<!-- lazy-init懒加载方式配置
默认false,容器读取配置后直接实例化
true,使用到(容器的getBean方法或其他方式)才会进行对象实例化
-->
<bean id="person3" class="com.blog.entity.Person" lazy-init="true"/>
7、自动注入(不常用)
当一个对象中需要引用另外一个对象的时候,在之前的配置中我们都是通过property标签来进行手动配置的,其实在spring中还提供了一个非常强大的功能就是自动装配,可以按照我们指定的规则进行配置,配置的方式有以下几种:
-
default/no:不自动装配
-
byName:按照名字进行装配,以属性名作为id去容器中查找组件,进行赋
值,如果找不到则装配null -
byType:按照类型进行装配,以属性的类型作为查找依据去容器中找到这个
组件,如果有多个类型相同的bean对象,那么会报异常,如果找不到则装配null -
constructor:按照构造器进行装配,先按照有参构造器参数的类型进行装
配,没有就直接装配null;如果按照类型找到了多个,那么就使用参数名作为id继续匹
配,找到就装配,找不到就装配null通过将autowire-candidate 属性设置为false,避免对bean定义进行自动装
配,如下一节所述。
通过将其 元素的primary属性设置为 true,将单个bean定义指定为主
要候选项。<!-- autowire 默认是不自动装配 byType表示通过类型自动装配,被当前对象引用的类的对象就不能配置两个 --> <bean id="child9" class="com.blog.entity.Child" autowire="byType"> </bean> <bean id="user7" class="com.blog.entity.User"> <property name="age" value="12"/> <property name="name" value="小龙女"/> <property name="userId" value="1123"/> </bean> ----------------------------------------------------------------- <!--autowire通过名称自动装配,那么Child的属性名称要和配置文件中bean的id属性一致,才能实现,找不到装配null--> <bean id="child10" class="com.blog.entity.Child" autowire="byName"/> <bean id="user" class="com.blog.entity.User" > <property name="age" value="12"/> <property name="name" value="小龙女"/> <property name="userId" value="1123"/> </bean> ---------------------------------------------------------------------- <!-- 自动注入可以结合手动注入使用,autowire通过构造方法注入会找对应引用类型的单独的构造方法,找到后根据类型进行配置,一般不做特殊配置,会配置最先扫描到的此类型的bean 没找到,配置为null --> <bean id="child11" class="com.blog.entity.Child" autowire="constructor"> <property name="name" value="123"/> </bean> 部分类代码示例 public class Child { private String name; private User user; public Child(User user2) { this.user = user2; }
8、命名空间简化配置
p命名空间简化通过setter方法依赖注入的配置
c命名空间简化通过构造方法依赖注入的配置
<!--添加相关约束-->
<beans xmlns:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c"
<!--注意定义默认的构造方法和带参数的构造方法发-->
<bean id="child5" class="com.blog.entity.Child" p:name="张飞" p:user-ref="user3"/>
<bean id="child6" class="com.blog.entity.Child" c:name="赵云" c:user-ref="user3"></bean>
9、关闭IOC容器
如果开发者在非Web应用环境使用Spring IoC容器的话(例如,在桌面客户端的环境下)开发者需要在JVM上注册一个关闭的钩子,来确保在关闭Spring IoC容器的时候能够调用相关的销毁方法来释放掉引用的资源。 当然,开发者也必须正确配置和实现那些销毁回调。
要注册关闭钩子,请调用ConfigurableApplicationContext
接口上声明的registerShutdownHook()
方法,如以下示例所示:
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Boot {
public static void main(final String[] args) throws Exception {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
// add a shutdown hook for the above context...
ctx.registerShutdownHook();
// app runs here...
// main method exits, hook is called prior to the app shutting down...
}
}
10、生命周期回调
a、继承InitializingBean和DisposableBean
测试结束,先执行构造方法,在执行初始化方法,容器关闭后对象销毁,又执行销毁方法
public class Wife implements InitializingBean, DisposableBean {
Wife(){
System.out.println("wife构造方法被执行");
}
@Override
public void destroy() throws Exception {
System.out.println("销毁方法被执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化方法被执行费");
}
}
<bean id="wife" class="com.blog.entity.Wife"/>
测试方法
/*
* 测试生命周期回调
* */
@Test
public void test06(){
Wife wife = context.getBean("wife", Wife.class);
System.out.println(wife);
context.close();
}
b、通过标签定义初始化方法和销毁方法
执行顺序请查看测试类输出结果
测试类
/**
* Auth : cloudinwinter 2021/2/19 11:37
* description : 测试生命周期回调
*/
public class Wife implements InitializingBean, DisposableBean {
Wife(){
System.out.println("wife构造方法被执行");
}
@Override
public void destroy() throws Exception {
System.out.println("销毁方法被执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化方法被执行费");
}
public void destoryMethod(){
System.out.println("标签调用销毁方法方法被执行");
}
public void initMethod(){
System.out.println("标签调用初始化方法被执行");
}
}
<bean id="wife" class="com.blog.entity.Wife" destroy-method="destoryMethod" init-method="initMethod"/>
/*
* 测试生命周期回调
* */
@Test
public void test06(){
Wife wife = context.getBean("wife", Wife.class);
System.out.println(wife);
context.close();
}
-----输出结果
wife构造方法被执行
初始化方法被执行费
标签调用初始化方法被执行
com.blog.entity.Wife@11438d26
销毁方法被执行
标签调用销毁方法方法被执行
11、通过工厂方法初始化bean
spring容器不再通过反射创建对象,而是通过调用工厂方法获取对象
a、通过静态方法初始化bean
<!--会找到当前类对应的方法,方法需要定义静态的-->
<bean id="wife" class="com.blog.entity.Wife" factory-method="createBean"/>
public class Wife /*implements InitializingBean, DisposableBean */{
Wife(){
System.out.println("wife构造方法被执行");
}
public static Wife createBean(){
return new Wife();
}
}
b、通过工厂类初始化bean
public class PersonFactory {
public Person createPerson(){
System.out.println("Person工厂方法被调用");
return new Person();
}
}
<!--会找到当前类对应的方法,方法需要定义静态的-->
<bean id="person" class="com.blog.entity.Person" factory-bean="PersonFactory" factory-method="createPerson"/>
12、scope配置对象单例多例设置
<!-- scope="prototype" : 多例(原型)每次获取都会创建一个对象
scope="singleton"(默认):通过此id获取的都是同一个对象。单例。
还有其他值比如request,一个请求一个对象。大概是用不上
-->
<bean id="user3" class="com.blog.entity.User" scope="prototype" >
<property name="age" value="12"/>
<property name="name" value="张飞"/>
<property name="userId" value="1123"/>
</bean>
13、xml配置中引入外部配置
<!-- 添加约束-->
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation中添加
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
<!-- 引入对应的配置文件-->
<context:property-placeholder location="db.properties"/>
<!--通过${}符号引入相关属性的值-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
<property name="url" value="${mysql.url}"/>
<property name="driverClassName" value="${mysql.driverClassName}"/>
</bean>
14、SpEL的使用
SpEL:Spring Expression Language,spring的表达式语言,支持运行时查询操作对象
使用#{…}作为语法规则,所有的大括号中的字符都认为是SpEL.
<bean id="user" class="com.blog.entity.User">
<!--支持任何运算符-->
<property name="age" value="#{12*2}"></property>
<!--可以引用其他bean的某个属性值-->
<property name="name" value="#{address.province}"></property>
<!--引用其他bean-->
<property name="role" value="#{address}"></property>
<!--调用静态方法-->
<property name="userId" value="#{T(java.util.UUID).randomUUID().toString().substring(0,4)}"></property>
<!--调用非静态方法-->
<property name="gender" value="#{address.getCity()}"></property>
</bean>
基于注解的配置(spring2.5)
注解的方式实现依赖注入,记住导入依赖。 配置文件和注解结合实现bean的注入
<!--
如果想要将自定义的bean对象添加到IOC容器中,需要在类上添加某些注解
Spring中包含4个主要的注解:
@Controller:控制器,推荐给controller层添加此注解
@Service:业务逻辑,推荐给业务逻辑层添加此注解
@Repository:仓库管理,推荐给数据访问层添加此注解
@Component:给不属于以上基层的组件添加此注解
注意:我们虽然人为的给不同的层添加不同的注解,但是在spring看来,这些注解的含义都是一样的,对应xml配置中的bean标签。
spring底层是不会给具体的层次验证注解,这样写的目的只是为了提高可读性,
最偷懒的方式就是给所有想交由IOC容器管理的bean对象添加component注解。
使用注解需要如下步骤:
1、 添加上述四个注解中的任意一个
2、添加自动扫描注解的组件,此操作需要依赖context命名空间
3、添加自动扫描的标签context:component‐scan
注意:当使用注解注册组件和使用配置文件注册组件是一样的,但是要注意:
1、组件的id默认就是组件的类名首字符小写,如果非要改名字的话,直接在注解中添加即可。
2、组件默认情况下都是单例的,如果需要配置多例模式的话,可以在注解下添加@Scope注解
-->
<!--
定义自动扫描的基础包:
base‐package:指定扫描的基础包,spring在启动的时候会将基础包及子包下所有加了注解的类都自动扫描进IOC容器
xmlns:context="http://www.springframework.org/schema/context"
-->
<context:component-scan base-package="com.blog"></context:component-scan>
<!--在@Value注解中使用配置文件属性,结合xml文件需要添加一下配置 -->
<context:property-placeholder location="db.properties"/>
项目结构如下:
在对应的类上添加注解,示例:
@Service
public class UserServiceImpl implements UserService {
}
设置需要扫描和需要排除扫描的注解
<!--
当定义好基础扫描的包之后,可以排除包中的某些类,使用如下的方式:
type:表示指定过滤的规则
annotation:按照注解进行排除,标注了指定注解的组件不要,expression表示要过滤的注解
assignable:指定排除某个具体的类,按照类排除,expression表示不注册的具体类名
aspectj:后面讲aop的时候说明要使用的aspectj表达式,不用
custom:定义一个typeFilter,自己写代码决定哪些类被过滤掉,不用
regex:使用正则表达式过滤,不用
-->
<context:component-scan base-package="com.blog">
<!--设定排除类型为注解类型,再设定要排除的注解的全限定类名称-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--use-default-filters默认为真,为扫描@controller@component等注解,为false不会扫描-->
<context:component-scan base-package="com.blog" use-default-filters="false">
<!--设定排除类型为注解类型,再设定要排除的注解的全限定类名称-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
设置注入容器的id
//默认是类名称小写进行注入,可以另行配置
@Controller("controller")
public class UserController {
}
//value默认可以忽略
@Controller(value = "controller")
value注解
/*
* 使用前类名称上要添加@Component注解或等效注解
* 设置对象属性
* 1、硬编码设置
* 2、使用${},配合xml配置文件,需要引入 <context:property-placeholder location="db.properties"/>
3、使用#{},可以使用spEL进行赋值
*
* */
@Value("张飞")
private String name;
@Value("#{role.name}")
private String name1;
@Value("#{T(java.util.UUID).randomUUID().toString().substring(0,4)}")
private String uuid;
@Value("${db.name}")
private String name3;
// 还可以配置非静态方法给静态属性赋值,
Autowired注解
@Primary
@Qualifier()
/*
* 通过Autowired实现引用类型赋值
* 1、会先根据类型去找对应的bean,如果有多个,或者一个接口有多个实现类,在类型的基础上会根据当前属性名称去匹配,没有配置上则会报错
* 2、如果定义了@Qualifier()注解,省略类型匹配的步骤,直接根据此注解的value值配配
* 3、当有多个匹配项时,可以在其中一个匹配项加上@Primary注解,表示这是一个首选对象
* */
@Autowired
@Qualifier("userServiceImpl")
UserService userService;
@Service
@Primary
public class UserServiceImpl implements UserService {
---------------------------------------------------------------
// 使用泛型作为自动注入的标识符,虽然名称不匹配,而且实现类又多个,但是可以根据泛型类型进行识别
public interface BaseServie<T> {
// 公共接口,实现公共的怎删改
T getBean();
}
@Service
public class ChildServiceImpl implements BaseServie<User> {
@Override
public User getBean() {
return new User();
}
}
@Autowired
BaseServie<User> userBaseServie;
public void getBean(){
userBaseServie.getBean();
}
使用在不同的位置
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
可以被使用在构造方法,方法,方法参数,属性,注解上
项目启动的时候就调用了,一般是用来赋值的,比如@value注解配置非静态方法给静态属性赋值,这一个可以给引用类型赋值,不常用哈。
/*
* Autowired使用在方法上
* */
@Autowired
public void getUser( @Qualifier("userServiceImpl")UserService userService){
userService.getUser();
}
public void getUser2( @Autowired UserService userService){
userService.getUser();
}
@AutoWired和@Resource
在使用自动装配的时候,出了可以使用@AutoWired注解之外,还可以使用@Resource注解,大家需要知道这两个注解的区别。
1、@AutoWired:是spring中提供的注解,@Resource:是jdk中定义的注解,依靠的是java的标准
2、@AutoWired默认是按照类型进行装配,默认情况下要求依赖的对象必须存在,@Resource默认是按照名字进行匹 配的,同时可以指定name属性。
3、@AutoWired只适合spring框架,而@Resource扩展性更好
@DependsOn
//改变对象加载到容器中的顺序
@Component
@DependsOn("user")
public class Role {
private User user;
}
@Lazy和@Lazy
@Component
@Lazy(false) // 默认我true,直接加载,设置为false,使用时加载
//@Scope("singleton")
@Scope("prototype") //默认单例,prototype为设置成多例
public class Role {
private User user;
}
@PostConstruct和@PreDestroy生命周期回调
// 生命周期初始化回调
@PostConstruct
public void init(){
System.out.println("初始化方法");
}
// 生命周期销毁回调
@PreDestroy
public void destory(){
System.out.println("摧毁对象回调");
}
基于Java的配置
通过配置类实现容器配置
@Test
public void test01(){
/*
* spring容器加载spring的配置类。一个是直接传入配置类,一个是指定对应的包,spring容器会自动扫描对应的配置类
* */
// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(IocJavaConfig.class);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.blog");
UserController controller = context.getBean("userController", UserController.class);
controller.getUser();
}
/*
* Configuration标记一个spring容器的配置类,之前是通过xml配置
* */
@Configuration
@ComponentScan(basePackages = "com.blog") // 配置扫描的包
@PropertySource("classpath:db.properties") // 引入配置文件,<context:property-placeholder location="db.properties"/>
/*
1、导入外部依赖(不需要在导入的类上面加@Component,使用此注解会为对应的类生成实例,当然加了也没影响),
2、导入另外的配置类作用等于<import resource="spring-ioc2.xml"/>
3、导入一个ImportSelector的实现类(我们仔细实现的),可以注册多个bean
4、导入ImportBeanDefinitionRegistrar的实现类,可以注册多个beanDefinition。
*/
@Import({User.class, IocJavaConfig2.class, MyImportSelector.class,MyImportBeanDefinnitionRegistrar.class})
public class IocJavaConfig {
@Value("${mysql.url}")
private String url;
@Value("${mysql.username}")
private String name;
@Value("${mysql.password}")
private String passWord;
@Value("${mysql.driverClassName}")
private String driverClass;
/*
* 将一个类的实例注册到ioc容器中(可以干预实例化的过程),等于<bean calss = "">标签的作用。
* 1、会自动将返回值作为bean的类型,将方法名作为bean的名字(id)
* 2、通过 @Bean(name = "dataSource")设置bean的别名
* 3、实现第三方类的配置
* 4.实现生命周期方法回调@Bean(destroyMethod = "init",initMethod = "destory")
* <bean id="wife" class="com.blog.entity.Wife" destroy-method="destoryMethod" init-method="initMethod"/>
* 5、单例和多例设置
* */
@Bean(name = "dataSource")
@Scope("prototype")
public DruidDataSource createDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setPassword(passWord);
dataSource.setUrl(url);
dataSource.setName(name);
dataSource.setDriverClassName(driverClass);
return dataSource;
}
/*
* 4.实现生命周期方法回调@Bean(destroyMethod = "init",initMethod = "destory")
* 5、设置为懒加载
* 6、使用外部依赖(外部bean),如果对应的外部bean已经通过@Component等方式注入到ioc容器(或者加上@Import(User.class)的方式),那么作为方法参数可以直接使用,
* 7、使用内部bean(配置类中@bean注解创建),直接调用@bean对应的方法即可
* */
@Bean(destroyMethod = "destory",initMethod = "init")
@Lazy(value = false)
public Role role(User user){
Role dataSource = new Role();
// 使用内部bean
System.out.println(user3());
return dataSource;
}
@Bean
public User user3(){
return new User();
}
}
@Component
public class MyImportBeanDefinnitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(Person.class);
registry.registerBeanDefinition("bean",beanDefinition);
}
}
//需要加载到ioc容器中才能生效
@Component
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//以字符串的形式返回多个bean,定义后只能通过类型获取,不能通过名称获取
return new String[]{Person.class.getName(), Wife.class.getName()};
}
}
@ImportResource
@Configuration
// 以javaconfig方式为主,引入xml配置方式
@ImportResource("classpath:spring.xml")
public class IocJavaConfig {
@Profile
@Configuration
public class AppConfig {
@Bean("dataSource")
@Profile("development") (1)
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") (2)
public DataSource jndiDataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
@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
@Profile("production")
public class JndiDataConfig {
@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();