02-IOC-DI
coupling 英 [ˈkʌplɪŋ] n. 连接;结合;联结;性交;联轴器;(连接车辆的)车钩
Spring配置文件,约定俗成applicationOOXX.xml
1. IOC
- 控制反转(Inversion_of_Control,缩写IoC),是面向对象编程中的一种设计原则,降低代码之间耦合度。最常见方式:
- 依赖注入(Dependency_Injection,简称DI),DI处理的是对象属性赋值和互相依赖关系
- 依赖查找(Dependency_Lookup)
- 创建对象的权利,控制的位置,由java代码转移到Spring容器。由Spring容器控制对象的创建,就是控制反转
- Spring创建对象时,会读取配置文件,反射创建好对象之后在容器中存储起来。需要对象时,通过id获取对象即可,不需要去new
- Bean(咖啡豆)。又称Java_Bean。其实就是java程序中的一个个对象,所以Bean管理其实就是Spring对java程序对象的管理。管理方式:
- 基于xml方式
- 基于注解方式
2. 解耦
- Service调用Dao层,需要new Dao层接口实现类对象。当Dao层接口实现类切换时,需要修改Service层代码,强耦合
- 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原理
- XML解析技术读取配置文件 => DOM4J
- 对象id,对象的类的全路径名
<bean id="db" class="com.listao.dao.Impl.Mysql"/>
- 反射技术实例化对象,放到容器中
// 类全路径名,获得类字节码
Class clazz = Class.forName("com.listao.dao.Impl.Mysql");
// 字节码实例化对象
Object obj = clazz.newInstance();
// 将对象放到map中
map.put("db", obj);
- 工厂模式返回Bean对象
BeanFactory
接口:IOC容器基本功能接口,Spring内部使用接口,业务处理一般不使用该接口ApplicationContext
接口:BeanFactory子接口,提供更强大功能,研发人员一般使用的接口
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>
- 依赖关系图
1. xml
- 快速创建spring配置文件
5. IOC创建对象
1. <bean>
属性
id
:对象的idclass
:类的全路径名name
:和id类似,一般不用lazy-init
:懒加载,getBean()
时再去实例化对象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
- 添加约束
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. 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. 转译字符 (< <)(> >)(& &)
2. <![CDATA[ ooxx ]]>
-->
<bean id="user_null" class="com.listao.pojo.User">
<property name="id">
<null/>
</property>
<property name="name" value="&<xiaomi>"/>
<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. 自动注入
<property>
标签手动注入- 自动装配,完成属性自动注入
byName
:ref="book"
和id="book"
一致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:德鲁伊,阿里开发
- 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>
- 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>
- 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=******
- 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()
- 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;
}
}
- xml
<!-- FactoryBean -->
<bean id="bookFactory" class="com.listao.pojo.BookFactory"/>
- 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()
- 第一阶段:
Cycle()
,无参构造 - 第二阶段:
set()
- 第三阶段:
init()
- 第四阶段:
getBean()
- 第五阶段:
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
ApplicationContext
自动检测配置文件中实现了BeanPostProcessor
接口的bean,并把它们注册为后置处理器- 初始化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
@Component
:类上,用于标记,告诉Spring当前类由容器实例化并放入容器中@Controller
:controller层bean@Service
:service层bean@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
@Autowired
:byType注入@Autowired
+@Qualifier
: byName注入。Spring下的注解@Resource
:byType多个,再byName(类名首字母小写)。JDK下javax包的注解@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();
}