发表于: 2020-04-30 11:24:27
1 1337
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)构造函数有两个参数时
- <constructor-argvalue="admin"index="0"></constructor-arg>
- <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,不然报错
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}
成功运行测试:
评论