发表于: 2020-04-30 11:24:27

1 1336


Spring的IOC控制反转和依赖注入

有时候类引用类又引用其他类,耦合过深:比如要初始化一个Test类,Test类引用了User又要先初始化User。

IOC(inversion of control)控制反转模式;控制反转是将组件间的依赖关系从程序内部提到外部来管理; 

DI(dependency injection)依赖注入模式;依赖注入是指将组件的依赖通过外部以参数或其他形式注入;

IOC将需要的所有类加载到一个容器里,统一初始化,使用时只需直接取出,不用再用new生成一个。

控制反转IOC是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IOC容器,它就是一个专门用来创建对象的工厂(BeanFactory),你要什么对象,它就给你什么对象,有了 IOC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IOC容器了,通过IOC容器来建立它们之间的关系。

参考链接:https://blog.csdn.net/u011055819/article/details/80848530


Spring的依赖注入分类:如何把放类放进容器里

Spring注入可以理解为是对一个对象进行初始化,也就是省去new的这个步骤,类似于工厂模式一样,通过一个工厂制造出这个对象,如果遇到修改,只需要改一处就行了

1.set注入:利用属性的set方法进行初始化。按左边可以直接跳转到set方法

public void setName(String name) {
this.name = name;
}
<!--set注入:要求Test类有set方法-->
<!--    把一个bean放入到容器里,就可以从容器中取用类,name写类的小写,class写类的地址-->
<bean id = "test" class = "dao.Test">
<!--    调用test的有参的初始化类,可以直接为属性赋值,或ref=dataSource把其他类赋值进去-->
   <property name = "name" value = "小名"/>
</bean>


2.构造注入:利用类的构造方法初始化

<!--构造注入-->
   <bean id = "test" class = "dao.Test">
       <constructor-arg name= "name" value = "小名"/>
   </bean>

 1)构造方法只有一个参数时

<constructor-argvalue="admin"></constructor-arg>

2)构造函数有两个参数时

  1. <constructor-argvalue="admin"index="0"></constructor-arg>                
  2. <constructor-argvalue="23" type="int"index="1"></constructor-arg>


3.使用注解

base-package为需要扫描的包(含所有子包),如果有多个包名可以用分号隔开(分号在引号中),然后再在目标类上面增加一些注解,如图

<!--    使用注解注入,base-pakage路径下所有用到注解的都会被装配进容器里-->
   <context:component-scan base-pakage="dao"/>

@Component 泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注,(把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>)

@Component
public class Test {

@service 服务(注入dao),用于标注业务层组件

@Controller 控制器(注入服务),用于标注控制层组件(如struts中的action) 

@Autowired 自动装配:类A中有对类B的依赖关系

@Autowired
private User user;

@Recource 作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。

Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

<bean id = "test" class = "dao.Test"/>
<bean id = "test1" class = "dao.Test"/>
@Autowired
private User user;
@Resources(name="test1")
private User user;

推荐使用:@Resource注解在字段上,这样就不用写setter方法了,并且这个注解是属于J2EE的,减少了与spring的耦合。这样代码看起就比较优雅。

参考:https://blog.csdn.net/lishuangzhe7047/article/details/20740835

https://blog.csdn.net/weixin_40423597/article/details/80643990

@ignore 跳过该测试方法不执行

@Test
   @Ignore
   public void deleteUser(){
Integer result = userDao.deleteUser(9L);//删除id为9
       System.out.println(result);
//        sqlSession.commit();
   }

@Text timeout

@Test(timeout = 10000)

@Runwith就是一个运行器

@RunWith(JUnit4.class)就是指用JUnit4来运行

@RunWith(SpringJUnit4ClassRunner.class),让测试运行于Spring测试环境


@ContextConfiguration Spring整合JUnit4测试时,使用注解引入多个配置文件

单个文件 

@ContextConfiguration(Locations="classpath:applicationContext.xml")  

@ContextConfiguration(classes = SimpleConfiguration.class)

多个文件时,可用{}

@ContextConfiguration(locations = { "classpath:spring1.xml", "classpath:spring2.xml" }) 

原文链接:https://blog.csdn.net/weixin_41315469/article/details/79675044


 数据库连接池,DataSource也是一个类,通过set方法把属性给注入进去

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
       <property name="dataSource" ref="dataSource"/>
<!--        自动扫描mapping.xml文件,这里是调用usermapper.xml-->
       <property name="mapperLocations" value="classpath:mappers/*.xml"/>
   </bean>

如果不用spring的配置文件,就要写这么多代码来new类(这里是applicationContext.xml)


Spring整合mybatis步骤

1.第一步,创建maven项目,搭基础架构分层。
2.第二步,实现pom文件的依赖。
3.第三步,配置resources下的文件。
4.第四步,创建测试类使用junit即可。


测试

断言结果为1,不然报错

assertEquals("1", result);

log4j.properties

#级别有ERROR DEBUG  WARN INFO
# Root logger  #info级别日志
log4j.rootLogger=INFO, A, file, C
#debug级别日志
#log4j.rootLogger=DEBUG, A, file, C

# Logging to console 输出信息到控制台
log4j.appender.A=org.apache.log4j.ConsoleAppender
log4j.appender.A.Target=System.out
log4j.appender.A.layout=org.apache.log4j.PatternLayout
log4j.appender.A.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n


# Direct log messages to a log file
#输出DEBUG级别的日志到/log.log
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=/Users/rongrongfu/Desktop/JAVAxiu/shutask1learn4/src/main/java/logs/log.log
log4j.appender.file.Append = true
log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%t] %-5p %c %x - %m%n
#log4j.appender.file.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%t:%r]-[%p] %m%n
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10

运行UserDaoTest报错:

java.lang.IllegalStateException: Failed to load ApplicationContext  通配符的匹配很全面, 但无法找到元素 'context:property-placeholder' 的声明。

重新写applicationContext.xml的头部文件

参考链接:https://www.jianshu.com/p/89388424a48c


运行UserDaoTest又报错:

java.lang.NoSuchMethodError: org.springframework.context.support.AbstractApplicationContext.clearResourceCaches()V

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-context</artifactId>
   <version>5.1.5.RELEASE</version>
</dependency>

原因:版本冲突。比如spring的jar里的A类调用mybatis jar中的B类C方法,但mybatis版本跟spring调用的那个版本对不上,B类里没有C方法,就会报错。所以spring系列jar全都改成:

${spring.version}


成功运行测试:


返回列表 返回列表
评论

    分享到