IOC容器概述

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"/>

项目结构如下:image-20210219215244523

在对应的类上添加注解,示例:

@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();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值