02-IOC-DI

coupling 英 [ˈkʌplɪŋ] n. 连接;结合;联结;性交;联轴器;(连接车辆的)车钩

Spring配置文件,约定俗成applicationOOXX.xml

1. IOC

  1. 控制反转(Inversion_of_Control,缩写IoC),是面向对象编程中的一种设计原则,降低代码之间耦合度。最常见方式:
    1. 依赖注入(Dependency_Injection,简称DI),DI处理的是对象属性赋值和互相依赖关系
    2. 依赖查找(Dependency_Lookup)
  2. 创建对象的权利,控制的位置,由java代码转移到Spring容器。由Spring容器控制对象的创建,就是控制反转
    • Spring创建对象时,会读取配置文件,反射创建好对象之后在容器中存储起来。需要对象时,通过id获取对象即可,不需要去new
  3. Bean(咖啡豆)。又称Java_Bean。其实就是java程序中的一个个对象,所以Bean管理其实就是Spring对java程序对象的管理。管理方式:
    1. 基于xml方式
    2. 基于注解方式

2. 解耦

  1. Service调用Dao层,需要new Dao层接口实现类对象。当Dao层接口实现类切换时,需要修改Service层代码,强耦合
  2. Service从Spring容器取Dao层接口实现类对象,容器中对象从Xml中读取通过反射创建。当Dao层接口实现类切换时,只需修改配置文件即可

1. 强耦合

/**
 * 强耦合,需要进行代码修改ooxx
 */
@Test
public void strong_coupling() {
    IDB db = new Mysql();
    // IDB db = new Oracle();
    db.connect();
}





 
 


public interface IDB {

    void connect();
}
public class Mysql implements IDB {

    @Override
    public void connect() {
        System.out.println("Mysql connected...");
    }
}
public class Oracle implements IDB {

    @Override
    public void connect() {
        System.out.println("Oracle connected...");
    }
}

2. 弱耦合

/**
 * 弱耦合
 * 具体接口的哪个实现类对象的创建,由xml决定,java不需要重新编译、部署。模块间耦合度降低
 */
@Test
public void weak_coupling() {
    // 获取容器
    ApplicationContext ac = new ClassPathXmlApplicationContext("x1_coupling.xml");
    IDB db = ac.getBean("db", IDB.class);
    db.connect();
}
<?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="db" class="com.listao.dao.Impl.Mysql"/>-->
    <bean id="db" class="com.listao.dao.Impl.Oracle"/>

</beans>





 
 


3. IOC原理

  1. XML解析技术读取配置文件 => DOM4J
    • 对象id,对象的类的全路径名
<bean id="db" class="com.listao.dao.Impl.Mysql"/>
  1. 反射技术实例化对象,放到容器中
// 类全路径名,获得类字节码
Class clazz = Class.forName("com.listao.dao.Impl.Mysql");
// 字节码实例化对象
Object obj = clazz.newInstance();
// 将对象放到map中
map.put("db", obj);
  1. 工厂模式返回Bean对象
    1. BeanFactory接口:IOC容器基本功能接口,Spring内部使用接口,业务处理一般不使用该接口
    2. ApplicationContext接口:BeanFactory子接口,提供更强大功能,研发人员一般使用的接口
image-20221005145953448

4. pom.xml

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.3.5</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.3.5</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>5.3.5</version>
</dependency>

<!-- 只导入spring-context即可 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.5</version>
</dependency>
<!-- 测试 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.1</version>
    <scope>test</scope>
</dependency>
image-20221005105522198
  • 依赖关系图
image-20221005105938677

1. xml

  • 快速创建spring配置文件
image-20221005142804003

5. IOC创建对象

1. <bean>属性

  1. id:对象的id
  2. class:类的全路径名
  3. name:和id类似,一般不用
  4. lazy-init:懒加载,getBean()时再去实例化对象
  5. scope:控制对象单例、多例、使用范围
    • singleton:单例(默认值), Spring_IOC容器中只会存在一个共享的bean实例
    • prototype:多例,每一次获取都会产生一个新实例
    • request:每一次HTTP请求产生一个新的bean,同时该bean仅在当前HTTP_request内有效
    • session:每一次HTTP请求产生一个新的bean,同时该bean仅在当前HTTP_session内有效
    • global session:标准的HTTP_Session作用域,不过它仅仅在基于portlet的web应用中才有意义
<!--
    1. 默认User无参构造
    2. name:早期的id,可为特殊符号
    3. lazy-init:懒加载,默认为false
    4. scope:jar项目(singleton, prototype),默认singleton。war项目会有更多选项
    5. class:类的全路径,必须有无参构造
-->
<bean id="user" class="com.listao.pojo.User"/>

<bean id="lazy-init" class="com.listao.pojo.User" lazy-init="true"/>

<!--
    1. scope="singleton" 默认,单例
    2. scope="prototype" 多例
-->
<bean id="prototype" class="com.listao.pojo.User" scope="prototype"/>
/*
    noArgConstructor
    ---------------------------
    user = User(id=null, name=null, pwd=null)
 */
@Test
public void getBean() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x2_ioc.xml");
    // debug,ApplicationContext直接调用无参构造
    User user = ac.getBean("user", User.class);
    System.out.println("=========================");
    System.out.println("user = " + user);
}

@Test
public void lazy_init() {
    // 懒加载,容器创建bean不会创建
    ApplicationContext ac = new ClassPathXmlApplicationContext("x2_ioc.xml");
    System.out.println("=========================");

    // debug,getBean()才调用无参构造
    User user = ac.getBean("lazy-init", User.class);
    System.out.println("lazy-init = " + user);
}

/*
   noArgConstructor
   ---------------------------
   noArgConstructor
   ---------------------------
   (prototype1 == prototype2) = false
   (user1 == user2) = true
 */
@Test
public void prototype() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x2_ioc.xml");
    System.out.println("=========================");

    User prototype1 = ac.getBean("prototype", User.class);
    User prototype2 = ac.getBean("prototype", User.class);

    System.out.println("(prototype1 == prototype2) = " + (prototype1 == prototype2));

    User user1 = ac.getBean("user", User.class);
    User user2 = ac.getBean("user", User.class);

    System.out.println("(user1 == user2) = " + (user1 == user2));
}

6. DI

T1_IOC_DI

@ToString
public class User {
    private Integer id;
    private String name;
    private String pwd;

    public User() {
        System.out.println("noArgConstructor");
        System.out.println("---------------------------");
    }

    public User(Integer id, String name, String pwd) {
        System.out.println(
                StrUtil.format("allArgConstructor <= id: {}, name: {}, pwd: {}", id, name, pwd)
        );
        this.id = id;
        this.name = name;
        this.pwd = pwd;
        System.out.println("---------------------------");
    }

    public void setId(Integer id) {
        System.out.println(StrUtil.format("setId <= id: {}", id));
        this.id = id;
    }

    public void setName(String name) {
        System.out.println(StrUtil.format("setName <= name: {}", name));
        this.name = name;
    }

    public void setPwd(String pwd) {
        System.out.println(StrUtil.format("setPwd <= pwd: {}", pwd));
        this.pwd = pwd;
    }
}

1. property

<!--
    1. 无参构造创建对象
    2. set()属性赋值
-->
<bean id="setUser" class="com.listao.pojo.User">
   <!-- 自动进行类型转换 -->
   <property name="id" value="1"/>
   <property name="name" value="张三"/>
   <property name="pwd" value="pwd"/>
</bean>
/*
    noArgConstructor
    ---------------------------
    setId <= id: null
    setName <= name: &<xiaomi>
    setPwd <= pwd: &<123456>
    user = User(id=1, name=张三, pwd=pwd)
 */
@Test
public void setter() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x2_ioc.xml");
    User user = ac.getBean("setUser", User.class);

    System.out.println("=========================");
    System.out.println("user = " + user);
}

2. constructor-arg

<!--
    1. 有参构造
    2. index形参索引
-->
<bean id="allArg" class="com.listao.pojo.User">
    <constructor-arg name="id" value="3"/>
    <constructor-arg name="name" value="admin"/>
    <constructor-arg name="pwd" value="root"/>
</bean>

<bean id="allArg_index" class="com.listao.pojo.User">
    <constructor-arg index="0" value="4"/>
    <constructor-arg index="1" value="admin"/>
    <constructor-arg index="2" value="root"/>
</bean>
@Test
public void allArg() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x2_ioc.xml");
    System.out.println("=========================");

    User user = ac.getBean("allArg", User.class);
    System.out.println("user = " + user);

    User user1 = ac.getBean("allArg_index", User.class);
    System.out.println("user1 = " + user1);
}

3. p&c

  1. 添加约束
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

http://www.springframework.org/schema/beans/spring-beans.xsd"
  1. 配置对象
<!--
    1. p命名空间,简化<property>
    2. c命名空间,简化<constructor-arg>
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:c="http://www.springframework.org/schema/c"
-->
<bean id="p_namespace" class="com.listao.pojo.User" p:id="1" p:name="p_namespace" p:pwd="111111"/>
<bean id="c_namespace" class="com.listao.pojo.User" c:id="2" c:name="c_namespace" c:pwd="222222"/>
@Test
public void namespace() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x2_ioc.xml");
    System.out.println("=========================");

    User p_namespace = ac.getBean("p_namespace", User.class);
    System.out.println("p_namespace = " + p_namespace);

    User c_namespace = ac.getBean("c_namespace", User.class);
    System.out.println("c_namespace = " + c_namespace);
}

4. null & 特殊符号

<!--
    1. null值
    2. 特殊符号
        1. 转译字符 (< &lt;)(> &gt;)(& &amp;)
        2. <![CDATA[ ooxx ]]>
-->
<bean id="user_null" class="com.listao.pojo.User">
   <property name="id">
      <null/>
   </property>

   <property name="name" value="&amp;&lt;xiaomi&gt;"/>
   <property name="pwd">
      <value><![CDATA[&<123456>]]></value>
   </property>
</bean>
/**
 * null及特殊字符,进行初始值
 */
@Test
public void _null() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x2_ioc.xml");
    System.out.println("=========================");

    User user_null = ac.getBean("user_null", User.class);
    System.out.println("user_null = " + user_null);
}

5. DI_ref

<!-- Date对象 -->
<bean id="date" class="java.util.Date"/>

<!-- 1. 引用外部bean -->
<bean id="mouse1" class="com.listao.pojo.Mouse">
    <property name="name" value="Jerry1"/>
    <property name="birthdate" ref="date"/>
</bean>

<!-- 2. 引用内部bean -->
<bean id="cat1" class="com.listao.pojo.Cat">
    <property name="name" value="Tom1"/>
    <property name="mouse">
        <bean class="com.listao.pojo.Mouse">
            <property name="name" value="Jerry2"/>
            <property name="birthdate">
                <bean class="java.util.Date"/>
            </property>
        </bean>
    </property>
</bean>

<!-- 3. 级联引入bean -->
<bean id="mouse2" class="com.listao.pojo.Mouse"/>
<bean id="cat2" class="com.listao.pojo.Cat">
    <property name="name" value="Tom2"/>
    <property name="mouse" ref="mouse2"/>
    <!-- 必须有get(),反射调用 -->
    <property name="mouse.name" value="Jerry3"/>
    <property name="mouse.birthdate">
        <bean class="java.util.Date"/>
    </property>
</bean>






 





 
 









 


 






@Data
public class Cat {
    private String name;
    private Mouse mouse;
}
@Data
public class Mouse {
    private String name;
    private Date birthdate;
}
/**
 * 1. 引用外部bean
 * 2. 引用内部bean
 * 3. 级联引入bean
 */
@Test
public void di() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x3_di.xml");

    Mouse mouse1 = ac.getBean("mouse1", Mouse.class);
    System.out.println("mouse1 = " + mouse1);

    Cat cat1 = ac.getBean("cat1", Cat.class);
    System.out.println("cat1 = " + cat1);

    Cat cat2 = ac.getBean("cat2", Cat.class);
    System.out.println("cat2 = " + cat2);
}

6. container

  • 增加命名空间
xmlns:util="http://www.springframework.org/schema/util"

http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
@Data
public class Student {
    private String[] books;
    private List<String> lists;
    private Set<String> sets;
    private Map<String, String> map;
    private List<Book> bookList1;
    private List<Book> bookList2;
}
<bean id="student" class="com.listao.pojo.Student">
   <!-- [] -->
   <property name="books">
      <array>
         <value>JAVA</value>
         <value>MySQL</value>
         <value>Spring</value>
      </array>
   </property>

   <!-- List<String> -->
   <property name="lists">
      <list>
         <value>JAVA</value>
         <value>MySQL</value>
         <value>Spring</value>
      </list>
   </property>

   <!-- Set -->
   <property name="sets">
      <set>
         <value>JAVA</value>
         <value>MySQL</value>
         <value>Spring</value>
      </set>
   </property>

   <!-- Map -->
   <property name="map">
      <map>
         <entry key="JAVA" value="ooxx"/>
         <entry key="Go" value="ooxx"/>
         <entry key="JVM" value="ooxx"/>
      </map>
   </property>

   <!-- List<Book> -->
   <property name="bookList1">
      <list>
         <ref bean="b1"/>
         <ref bean="b2"/>
         <ref bean="b3"/>
      </list>
   </property>

   <property name="bookList2" ref="util_list"/>
</bean>

<bean id="b1" class="com.listao.pojo.Book" p:name="JAVA" p:author="ooxx"/>
<bean id="b2" class="com.listao.pojo.Book" p:name="Go" p:author="ooxx"/>
<bean id="b3" class="com.listao.pojo.Book" p:name="JVM" p:author="ooxx"/>

<!--
    定义公共集合
        xmlns:util="http://www.springframework.org/schema/util"
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd
-->
<util:list id="util_list">
    <bean id="b4" class="com.listao.pojo.Book" p:name="JAVA" p:author="ooxx"/>
    <bean id="b5" class="com.listao.pojo.Book" p:name="Go" p:author="ooxx"/>
    <bean id="b6" class="com.listao.pojo.Book" p:name="JVM" p:author="ooxx"/>
</util:list>
/*
    private String[] books;
    private List<String> lists;
    private Set<String> sets;
    private Map<String, String> map;
    private List<Book> bookList1;
    private List<Book> bookList2;
 */
@Test
public void di_container() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x3_di.xml");

    Student stu = ac.getBean("student", Student.class);

    System.out.println("stu.getBooks() = " + Arrays.toString(stu.getBooks()));
    System.out.println("stu.getLists() = " + stu.getLists());
    System.out.println("stu.getSets() = " + stu.getSets());
    System.out.println("stu.getMap() = " + stu.getMap());
    System.out.println("stu.getBookList1() = " + stu.getBookList1());
    System.out.println("stu.getBookList2() = " + stu.getBookList2());
}

7. 自动注入

  1. <property>标签手动注入
  2. 自动装配,完成属性自动注入
    1. byNameref="book"id="book"一致
    2. byType:根据类型注入,容器中只有一个type类型实例
@ToString
@Setter
public class Autowire {
    private One one;
    private One byType;
}

@ToString
class One {
    private String name;
}
<!-- 手动注入 -->
<bean id="one" class="com.listao.pojo.One"/>
<bean id="manual" class="com.listao.pojo.Autowire">
    <property name="one" ref="one"/>
    <property name="byType" ref="one"/>
</bean>

<!-- byName:属性根据id注入 -->
<bean id="autowire_byName" class="com.listao.pojo.Autowire" autowire="byName"/>

<!-- byType:属性根据class注入 -->
<bean id="autowire_byType" class="com.listao.pojo.Autowire" autowire="byType"/>








 


 
/*
 * 1. autowire="byName":<bean>属性根据id注入
 * 2. autowire="byType":<bean>属性根据class注入
 */
@Test
public void autowire() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x3_di.xml");

    Autowire byName = ac.getBean("autowire_byName", Autowire.class);
    System.out.println("byName = " + byName);

    Autowire byType = ac.getBean("autowire_byType", Autowire.class);
    System.out.println("byType = " + byType);
}

8. properties

# 1. DataSource:Spring自带连接池
# 2. C3p0
# 3. Druid:德鲁伊,阿里开发
  1. pom.xml
<!-- druid连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.10</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.22</version>
</dependency>
  1. xml
xmlns:context="http://www.springframework.org/schema/context"

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
<!-- druid.properties -->
<context:property-placeholder location="classpath:druid.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="url" value="${jdbc_url}"/>
    <property name="driverClassName" value="${jdbc_driver}"/>
    <!-- ${username}被Spring变量占用 -->
    <property name="username" value="${jdbc_username}"/>
    <property name="password" value="${jdbc_password}"/>
    <!-- 初始化容量(否则Connection refused时会弹出n次报错) -->
    <property name="initialSize" value="1"/>
</bean>

 









  1. properties
jdbc_driver=com.mysql.cj.jdbc.Driver
jdbc_url=jdbc:mysql://ip:port/mca?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
jdbc_username=******
jdbc_password=******
  1. java
@Test
public void properties() throws SQLException {
    ApplicationContext ac = new ClassPathXmlApplicationContext("di_ref.xml");

    DruidDataSource dds = ac.getBean("dataSource", DruidDataSource.class);
    System.out.println(dds);
    System.out.println("dds.getUrl() = " + dds.getUrl());
    System.out.println("dds.getDriverClassName() = " + dds.getDriverClassName());
    System.out.println("dds.getUsername() = " + dds.getUsername());
    System.out.println("dds.getPassword() = " + dds.getPassword());

    DruidPooledConnection conn = dds.getConnection();
}
{
	CreateTime:"2023-08-10 09:47:39",
	ActiveCount:0,
	PoolingCount:0,
	CreateCount:0,
	DestroyCount:0,
	CloseCount:0,
	ConnectCount:0,
	Connections:[
	]
}
dds.getUrl() = jdbc:mysql://ip:port/mca?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
dds.getDriverClassName() = com.mysql.cj.jdbc.Driver
dds.getUsername() = ******
dds.getPassword() = ******
2023-08-10 09:47:39 [main] INFO  DruidDataSource:930 - {dataSource-1} inited

7. FactoryBean

T1_IOC_DI.FactoryBean()

  1. FactoryBean实现类
/*
 * implements FactoryBean<Book>
 */
public class BookFactory implements FactoryBean<Book> {

    @Override
    public Book getObject() {
        Book book = new Book();
        book.setName("new Book()");
        book.setAuthor("BookFactory");
        return book;
    }

    @Override
    public Class<?> getObjectType() {
        return null;
    }
}



 














  1. xml
<!-- FactoryBean -->
<bean id="bookFactory" class="com.listao.pojo.BookFactory"/>
  1. java
/*
 * implements FactoryBean<Book>
 * 注入的是BookFactory,生产是Book
 */
@Test
public void FactoryBean() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x3_di.xml");

    Book book = ac.getBean("bookFactory", Book.class);
    System.out.println("book = " + book);
}

8. 生命周期

T1_IOC_DI.cycle()

  1. 第一阶段:Cycle(),无参构造
  2. 第二阶段: set()
  3. 第三阶段: init()
  4. 第四阶段:getBean()
  5. 第五阶段:destroy()
@ToString
public class Cycle {
    private String name;

    public Cycle() {
        System.out.println("第一阶段: Cycle(),无参构造");
    }

    public void setName(String name) {
        System.out.println("第二阶段: set()");
        this.name = name;
    }

    public void init() {
        System.out.println("第三阶段: init()");
    }

    public void destroy() {
        System.out.println("第五阶段: destroy()");
    }
}
<bean id="cycle" class="com.listao.pojo.Cycle" init-method="init" destroy-method="destroy">
    <property name="name" value="ooxx"/>
</bean>
/*
    第一阶段: Cycle(),无参构造
    第二阶段: set()
    ==========================> init()_Before
    第三阶段: init()
    ==========================> init()_After
    第四阶段: getBean()
    第五阶段: destroy()
*/
@Test
public void cycle() {
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("x4_cycle.xml");

    System.out.println("第四阶段: getBean()");
    Cycle cycle = ac.getBean("cycle", Cycle.class);

    // AbstractApplicationContext实现类才有close()
    ac.close();
}

9. BeanPostProcessor

  1. ApplicationContext自动检测配置文件中实现了BeanPostProcessor接口的bean,并把它们注册为后置处理器
  2. 初始化bean:init()的前后执行处理
/**
 * implements BeanPostProcessor
 * 重写接口的default方法
 */
public class BeanProcesser implements BeanPostProcessor {

    /**
     * postProcessBeforeInitialization
     *
     * @param bean      要干预的bean
     * @param beanName  xml_bean id
     * @return Object   返回bean,不能为null
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("==========================> init()_Before");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("==========================> init()_After");
        return 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="cycle" class="com.listao.pojo.Cycle" init-method="init" destroy-method="destroy">
        <property name="name" value="ooxx"/>
    </bean>

    <!-- 配置后置处理器,作用于该xml所有bean -->
    <bean id="beanProcesser" class="com.listao.pojo.BeanProcesser"/>
</beans>

10. DI_anno

T2_Annotation

  1. @Component:类上,用于标记,告诉Spring当前类由容器实例化并放入容器中
  2. @Controller:controller层bean
  3. @Service:service层bean
  4. @Repository:dao层bean

1. 注解IOC

<!--
    1. 扫描指定的包及子包,将包中注解类实例化
    2. 有多个包需要扫描,使用逗号隔开com.listao.bean,com.listao.service
    3. 注解指定bean的id,@Component("user")
    4. 如果不指定,则默认id,类名首字母小写
-->
<context:component-scan base-package="com.listao"/>

<!--
    1. use-default-filters="true" 默认的扫描过滤器,识别并包含@Component, @Controller, @Service, @Repository
    2. include-filter:扫描哪些IOC注解
    3. exclude-filter:不扫描哪些IOC注解
-->
<context:component-scan base-package="com.listao.annotation" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

<context:component-scan base-package="com.listao.annotation" use-default-filters="true">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>






 













@ToString
// <bean id="hasId_y" />
@Component("hasId_y")
public class HasId {
    private String name;
}
@ToString
// 默认id,类名首字母小写
@Component
public class NoId {
    private String name;
}
@Test
public void component_scan() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x5_annotation.xml");

    // 注解指定bean的id,@Component("user")
    HasId hasId = ac.getBean("hasId_y", HasId.class);
    System.out.println("hasId = " + hasId);

    // 如果不指定,则默认id,类名首字母小写
    NoId noId = ac.getBean("noId", NoId.class);
    System.out.println("noId = " + noId);
}

@Test
public void exclude() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x5_annotation.xml");

    Exclude exclude = ac.getBean("exclude", Exclude.class);
    System.out.println("exclude = " + exclude);
}
@ToString
@Controller
public class Exclude {
}

2. 注解DI

  1. @Autowired:byType注入
  2. @Autowired + @Qualifier: byName注入。Spring下的注解
  3. @Resource:byType多个,再byName(类名首字母小写)。JDK下javax包的注解
  4. @Value:注入普通数据类型(8种基本类型 + String)
password=ooxx
age=18
<context:component-scan base-package="com.listao"/>

<!-- 引入properties,classpath:*.properties -->
<context:property-placeholder location="classpath:druid.properties"/>
@Service
public class ServiceImpl {

    /*
     * @Autowired:byType注入
     * @Autowired + @Qualifier: byName注入。Spring下的注解
     */
    @Autowired
    @Qualifier(value = "daoA")
    private IDao iDaoA;

    /*
     * @Resource,JDK下javax包的注解
     * 1. byType: 有多个
     * 2. byName: 判断name
     */
    // @Resource
    @Resource(name = "daoB")
    private IDao iDaoB;

    // ${}获取系统变量值,或者.properties属性配置文件中的值
    @Value(value = "松松")
    private String name;
    @Value(value = "${password}")
    private String pwd;
    @Value(value = "${age}")
    private Integer age;

    public void annotation_di() {
        System.out.println("ServiceImpl");
        iDaoA.sel();
        iDaoB.sel();

        System.out.println("@Value: " + name + ", " + pwd + ", " + age);
    }
}







 
 








 


















@Test
public void di_xml() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("x5_annotation.xml");

    ServiceImpl si = ac.getBean("serviceImpl", ServiceImpl.class);
    si.annotation_di();
}

3. Config

@ComponentScan(basePackages = "com.listao")   // 包扫描
@PropertySource("classpath:druid.properties") // 配置文件读取
public class C1_IOC_DI {
}
 
 


  • AnnotationConfigApplicationContext
@Test
public void di_cfg() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(C1_IOC_DI.class);

    ServiceImpl si = ac.getBean("serviceImpl", ServiceImpl.class);
    si.annotation_di();
}