第四章、Spring 依赖注入

第四章、Spring 依赖注入

一、构造器注入

构造器注入bean子节点constructor-arg节点

可以使用constructor-arg节点属性index,name,type

基本类型注入:使用value

引用类型注入:使用ref
在这里插入图片描述

1、index 构造方法参数的索引

public StudentService(String name, StudentDao studentDao) {
    
    
		System.out.println("StudentService(name,studentDao)构造方法...name="+name+",studentDao="+studentDao);
		this.name = name;
		this.studentDao = studentDao;
	}
<bean id="studentDao" class="com.tjetc.dao.StudentDao"></bean>
 <bean id="studentService" class="com.tjetc.service.StudentService">
  <constructor-arg index="0" value="张三"></constructor-arg>
  <constructor-arg index="1" ref="studentDao"></constructor-arg>
</bean>

2、name 构造方法参数的名称

<bean id="studentDao" class="com.tjetc.dao.StudentDao"></bean>
 <bean id="studentService" class="com.tjetc.service.StudentService">
  <constructor-arg name="name" value="张三2"></constructor-arg>
  <constructor-arg name="studentDao" ref="studentDao"></constructor-arg>
</bean>

3、type 构造方法参数的类型

<bean id="studentDao" class="com.tjetc.dao.StudentDao"></bean>
 <bean id="studentService" class="com.tjetc.service.StudentService">
  <constructor-arg name="name" type="java.lang.String" value="张三2"></constructor-arg>
  <constructor-arg name="studentDao" ref="studentDao"></constructor-arg>
</bean>

二、属性set方法注入

使用bean类的属性的set方法注入属性值:

​ 1.bean类添加属性的setter方法

​ 2.在bean的子节点property

name:是setXxx()方法后单词的首字母变小写后的单词,不是属性名

value:代表的是值

ref:代表的是引用类型的bean的id的值

<bean id="studentDao" class="com.tjetc.dao.StudentDao"></bean>
 <bean id="studentService" class="com.tjetc.service.StudentService">
  <property name="xxx" value="李四"></property>
  <property name="studentDao" ref="studentDao"></property>
</bean>

Set注入与构造器注入对比:

扫描二维码关注公众号,回复: 11944813 查看本文章
  • Set注入模式代码更加简洁
  • 构造器注入对依赖关系的表达更加清楚
  • Set注入可以避免循环依赖问题

三、集合属性注入

1、list

(1)基本数据类型
<property name="hobbies">
      <list>
       <value></value>
       <value></value>
       <value></value>
       <value></value>
       <value>读书</value>
      </list>
</property>
(2)引用类型
<property name="books">
     <list>
      <ref bean="book1"/>
      <ref bean="book2"/>
      <ref bean="book3"/>
     </list>
</property>

2、数组(与list相同)

3、set(把list标签改为set标签,其他与list一样)

4、map

(1)基本数据类型
<property name="hobbies">
			<map>
			 <entry key="chi" value=""></entry>
			 <entry key="he" value=""></entry>
			 <entry key="wan" value=""></entry>
			</map>
</property>
(2)引用类型
 <property name="books">
			<map>
			 <entry key="xi" value-ref="book1"></entry>
			 <entry key="dong" value-ref="book2"></entry>
			 <entry key="nan" value-ref="book3"></entry>
			</map>
</property>

5、properties

<property name="properties">
		  <props>
		    <prop key="pk1">pv1</prop>
		    <prop key="pk2">pv2</prop>
		    <prop key="pk3">pv3</prop>
		    <prop key="pk4">pv4</prop>
		  </props>
		</property>
Properties properties = student.getProperties();
		Set<Object> keySet2 = properties.keySet();
		for (Object k : keySet2) {
    
    
//			String k=(String) object;
			System.out.println(properties.get(k));

四、p命名空间

简化property节点

1、引入p命名空间

xmlns:p="http://www.springframework.org/schema/p"

2、使用p命名空间

(1)基本数据类型

p:属性=值

(2)引用类型

p:属性-ref=另一个bean的id的值

<bean id="book" class="com.tjetc.domain.Book" p:name="西游记" p:price="30"></bean>
<bean id="student" class="com.tjetc.domain.Student" p:name="张三" p:book-ref="book"></bean>

五、c命名空间

简化constructor-arg节点

1、引入c命名空间

xmlns:c="http://www.springframework.org/schema/c"

2、使用c命名空间

(1)基本数据类型

c:构造方法参数名=值

(2)引用类型

c:构造方法参数名-ref=另一个bean的id的值

<bean id="book" class="com.tjetc.domain.Book" p:name="西游记" p:price="30"></bean>
<bean id="student" class="com.tjetc.domain.Student" c:name="李四" c:book-ref="book"></bean>

六、depends-on属性

B中没有A,在applicationContext.xml中配置depends-on=“a”,则先实例化A,再实例化B,销毁是先销毁B,再销毁A

结论:依赖对象先创建后销毁.

public class A {

	public A() {
		System.out.println("A()...");
	}
	
	public void init() {
		System.out.println("A.init()...");
	}
	public void destroy() {
		System.out.println("A.destroy()...");
	}

}
public class B {
    
    

	public B() {
    
    
		System.out.println("B()...");
	}
	
	public void init() {
    
    
		System.out.println("B.init()...");
	}
	public void destroy() {
    
    
		System.out.println("B.destroy()...");
	}
	
	public void say() {
    
    
		System.out.println("say():hello...");
	}

}
<bean id="b" class="com.tjetc.domain.B" depends-on="a" init-method="init" destroy-method="destroy"></bean>
<bean id="a" class="com.tjetc.domain.A" init-method="init" destroy-method="destroy"></bean>
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		B b = context.getBean(B.class);
		b.say();
		context.close();

A()...

A.init()...

B()...

B.init()...

say():hello...

B.destroy()...

A.destroy()...

七、延迟加载lazy-init

ApplicationContext的默认行为就是在创建IOC容器时将所有singleton 的bean提前进行实例化。

系统默认配置是lazy-init=“false”

当配置lazy-init="true"后,当第一次调用bean对象时,才进行实例

1、lazy-init="true"创建IOC容器时没有实例化bean,当第一次调用context.getBean(C.class)才进行实例化bean
2、lazy-init="true"只对当前的bean有效,对其他的bean不起作用
3、让所有的bean都设置成懒加载

​ beans节点设置 default-lazy-init=“true” ,让所有的bean都设置成懒加载.

4、default-lazy-init=“true” 所有bean懒加载的前提下,设置某个bean不懒加载 bean设置lazy-init=“false”

八、Spring注解配置Bean

Spring自动扫描bean,把类上有@Componet,@Controller,@Service,@Repository注解的bean纳入Spring容器管理

  • @Component 不好分层的时候用该注解
  • @Controller 控制层使用的注解
  • @Service 业务层使用该注解
  • @Repository dao层使用的注解

扫描包内注解的类**<context:component-scan base-package=”com.tjetc”>**

让spring扫描com.tjetc包及其子孙包下的在类上有@Component,@Controller,@Service,@Repository之一注解的类,Spring会把含有这些注解的类纳入spring管理,就相当于在applicationContext.xml配置了<bean id="" class="xxx.yyy.类">

九、AutoWire注入

1.自动注入,默认按类型注入

2.如果同一接口有多个实现类就相当于同一个类型在spring容器中有多个相同类型的对象,Spring不知道使用哪一个对象,需要我们告诉他:

  • 把成员变量的名字改为spring容器中bean的名字
  • 把要用的实现类中@Repository(“成员变量的名字”)
  • 把不用的类上的注解去掉(不推荐使用)
  • 在每个实现类的注解写不同的名字,在引用的地方在@AutoWired 后面写@Qualified(“bean的名字”) --推荐使用
@Service//<bean id="userServiceImpl" class="com.tjetc.service.impl.UserServiceImpl">
public class UserServiceImpl implements UserService {
    
    
    @Autowired//让容器把它创建好的对象注入进来,依赖注入DI:Dependency Injection
    private  UserDao userDao;
    @Override
    public void login() {
    
    
      userDao.login();
    }
}


@Repository//<bean id="userDao" class="com.tjetc.dao.impl.UserDaoImpl">
public class UserDaoImpl implements UserDao {
    
    
    @Override
    public void login() {
    
    
      System.out.println("UserDaoImpl.login()...");
    }
}
@Qualifier按照名称注入
@Service//<bean id="userServiceImpl" class="com.tjetc.service.impl.UserServiceImpl">
public class UserServiceImpl implements UserService {
    
    
    //@Autowired:自动注入,默认按类型注入
    @Autowired//让容器把它创建好的对象注入进来,依赖注入DI:Dependency Injection
    //@Qualifier("userDaoOracle")//按照名称注入
    private  UserDao userDao;//userDaoMysqlImpl:bean的名称

    @Override
    public void login() {
    
    
      	userDao.login();
    }
/**
 * <bean id="userDaoMysqlImpl" class="com.tjetc.dao.impl.UserDaoImpl">
 * <bean id="userServiceImpl" class="com.tjetc.service.impl.UserServiceImpl">
 *   <property name="userDao" ref="userDaoMysqlImpl">
 * </bean>
 */
}
Autowired模式的缺陷
  1. 对于java基本类型和String等简单类型,无法使用Autowire方式注入
  2. 业务变化,注入的配置项必须改变时,没有xml配置修改容易。例如:
    @Component(“userDaoMysql”)
    public class UserDaoMySqlImpl implements UserDao{
  3. 同一接口的多个实现类同时使用时,容易引发冲突

十、Spring中,支持 5种 自动装配模式

Spring支持5种自动装配模式

  1. no——默认情况下,不自动装配,通过“ref”attribute手动设定。
  2. byName——根据Property的Name自动装配,如果一个bean的name,和另一个bean中的Property的name相同,则自动装配这个bean到Property中。
  3. byType——根据Property的数据类型(Type)自动装配,如果一个bean的数据类型,兼容另一个bean中Property的数据类型,则自动装配。
  4. constructor——根据构造函数参数的数据类型,进行byType模式的自动装配。
  5. autodetect——如果发现默认的构造函数,用constructor模式,否则,用byType模式。

在这里插入图片描述

十一、Bean的scope属性

(一)单例singletone

​ 当定义一个bean定义并且它的作用域是一个singleton时,Spring IoC容器创建由该bean定义的对象的一个实例。 这个单实例存储在这个单例bean的缓存中,该bean的所有后续请求和引用都返回从缓存中获得对象。与golf的单例模式不一样的.

spring容器默认scope的是singleton

注意:scope=singleton情况下,bean的构造方法什么时候执行的?

答:实例化容器的时候执行.

(二)多例prototype

​ 当scope="prototype"时,每次调用getBean(“bean的名称”),都会生成一个新的对象。

注意:scope=prototype情况下,bean的构造方法什么时候执行的?

答:实例化容器的时候不执行.每次调用getBean(“bean的名称”)的时候执行.

十二、Bean的生命周期回调处理(bean初始化和销毁)

  • 使用JSR-250 @PostConstruct 和 @PreDestroy 是bean对象生命周期callback的最好方式。
  • 使用Spring 的InitializingBean 和 DisposableBean 接口也可以。使用接口的弊端是callback管理与Spring的代码产生了耦合,带来了不必要的麻烦。

猜你喜欢

转载自blog.csdn.net/yubo_830/article/details/106363113