04_Spring–ioc和di
文章目录
Spring框架的地位
- Java职业生涯离不开Spring
- Spring框架基于IOC和AOP思想做了很好的实现
- Spring框架向着全家桶趋势发展
Spring的介绍
-
什么是Spring?
- Spring在经典三层都有实现
- Spring是一个一站式/全栈式的解决方案(Spring框架可以开发web层,service层,dao层)
Spring本质是一个对象的容器,可以管理web,service,dao层等对象
-
官方描述:
Spring是分层的JavaSE/EE应用的full-stack轻量级开源框架,以IOC(控制反转)和AOP(面向切面编程)为内核,提供了展现层SpringMVC和持久层SpringJdbcTemplate以及业务层事务管理等众多企业级应用技术,还能整合开源世界众多著名的第三方框架和类库,逐渐成为使用最多的JavaEE框架
Spring优势
- 方便解耦合,简化开发
- 通过Spring提供的IOC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必在为单实例模式类,属性文件解析等这些很底层的需求编写代码,可以专注于上层的应用
- AOP编程的支持
- 通过Spring提供的AOP功能,方便的及新娘面向写main编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应对
- 声明式事务
- 编程式事务:直接把事务的控制代码添加到业务代码上来控制事务的方式叫编程是事务
- 声明式事务:直接通过XML配置或者注解完成事务的控制
- 在Spring中,我们从单调的事务管理代码中解脱出来,通过声明式来进行事务的管理,提高开发效率和质量
- 方便程序的测试(Spring对junit支持)
- 可以用非容器依赖的编程方式进行所有的测试工作,在Spring里,测试不在式昂贵的操作,而是随手可以做的事情。例如:Spring对junit4的支持,通过注解的测试Spring程序
- 方便继承各种优秀的框架
- Spring不排除各种优秀的开源框架,相反Spring可以降低各种框架的使用难度,Spring提供了各种优秀的框架的支持
- Spring的包容性非常强,可以无缝集成第三方框架
- 降低了Java EE API 的使用难度
- API应用程序接口
- Spring对很多比较难用的JavaEE API(如jdbcmJavaMile,远程调用等)提供了一个封装层,通过Spring的简易封装,这些JavaEE API的使用难度大为降低
- Java源码是的经典学习的范例
ioc的概念和作用
Spring主要就是对IOC和AOP思想的技术实现
注意 ioc和aop在Spring之前就已经存在,只不过偏向于理论化而已,Spring对着两个思想做了很好的技术实现
- IOC的概念
IOC(控制反转/反转控制),所谓正向就是一个类A依赖另外一个类B完成功能的时候我们会在程序中new一个B的对象,反向指的是new对象过程不在程序中我们自己完成,而是交给框架,由框架帮我们创建对象,我们世界问框架要对象即可
IOC的本质就是帮助我们new对象
- IOC的作用
解决了程序耦合问题
- 关于程序耦合(认识)
耦合:就是耦合度
耦合不可避免,只能降低耦合
“高内聚”,“低耦合”
自定义ioc实现解耦合
开发Dao层和Service层保存账户,不具体操作数据库
public class BeanFactory {
private static Map<String, Object> map = new HashMap<>();
static {
InputStream inputStream = BeanFactory.class.getClassLoader().getResourceAsStream("Account.xml");
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(inputStream);
Element rootElement = document.getRootElement();
List<Element> list = rootElement.selectNodes("//bean");
if (list != null && list.size() > 0) {
for (int i = 0; i < list.size(); i++) {
Element element = list.get(i);
String id = element.attributeValue("id");
String aClass = element.attributeValue("class");
Class<?> o = Class.forName(aClass);
Object o1 = o.newInstance();
map.put(id, o1);
}
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
public static Object getBean(String id) {
return map.get(id);
}
@Test
public void testBeanFactory() throws Exception {
AccountService service = (AccountService) BeanFactory.getBean("accountService");
service.saveAccount(new Account());
}
使用SpringIOC实现程序解耦合
Springioc的细节知识
ApplicationContext接口的实现类
Bean管理细节
Bean标签
-
id标识符,定位对象。id不能重复
-
class:所创建对象的全限定类名。不能配置为接口,因为接口不能实例化
-
scope:对象的作用范围,单例和多例.
- singleton:单例,默认bean的scope都是单例
- prototype:多例的意思,没getBean一次就new一个新的对象
- request:在web应用的一个request请求内有效,下个请求就要重新new一个对象
- session:在web应用的一个session请求内有效,下个请求内就重新new一个对象
-
生命周期属性:
-
bean即对象,独享就有生命周期,生命周期就有开始和结束,有时候希望在对象创建之后立马做的事情,胡总和在销毁之前立刻做的事情
注意
- 需要手动关闭容器
- scope需要设置为singleton
-
-
对象创建的三种方式
-
通过配置文件创建
-
静态方法(自己new独享,然后加入到Spring的对象容器中管理)
-
动态实例化方法(自己new对象,然后加入到Spring的对象容器中管理需要事先轻易工厂类的bean,然后通过工厂bean独享调用里面的方法返回具体的对象)
-
依赖注入di
di 依赖注入,注入对象所依赖的对象
set注入
也叫设值注入
构造函数注入
复杂对象注入
Springioc和di的注解实现
Springioc的注解实现
原则:找xml中配置项和注解的对应
注意:使用注解不需要引入额外的jar包
标签定义一个对象 ------@Component(“accpountDao”)(bean的id属性直接配置在注解后面,如果不配置,默认定义这个bean的id为类名小写,针对分层代码开发,提供了@Controller,
@Service,@Repository)
scope属性-----@Scope(“prototype”)默认单例
init-method属性------@PostConstruct
destroy-method属性----@PreDestory
注解注入方式:
@Autowire(Spring框架提供,推荐使用)-----根据类型注入
@Resource注解 (jdk提供)----根据id注入
开启注解扫描
半xml半注解的实现
使用最多
xml配置文件一九存在,从配置文件启动容器
半xml:指的是第三方jar中的对象的定义在配置文件中,
半注解:自己定义的类使用注解的方式
纯注解的方式实现
纯注解方式实现(不需要引入额外的jar)
其实是对半xml的进一步该走
-
重点是改造第三方jar中的定义(注解实现)
-
容器初始胡不是加载xml的方式了(纯注解不存在xml文件了)
-
@Configuration注解,表明当前类一个配置类
-
@ComponentScan注解,替代context:component-scan
-
@Value对变量赋值,可以直接赋值,也可以使用${}读取资源配置文件中的信息
启动容器测试
注意:
使用Spring的时候,查找资源文件,咱们统一养成习惯加上classpath:
classpath:和classpath*:的区别,classpath会去工程classes目录下查找(不包括jar)
classpath*会包括jar的所有的classes下去查找
Spring对Junit的支持
-
引入jar包
<!--Spring对junit测试的支持--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.2.RELEASE</version> </dependency>
-
Spring对junit支持所带来的好处
-
配置之后不需要我们去启动容器
-
测试那个独享直接可以注入(使用注解)
纯注解启动的形式
// 使用Spring自定义的junit运行器替换它默认的运行器 @RunWith(SpringJUnit4ClassRunner.class)
-
// 指定配置文件或者配置类
@ContextConfiguration(classes = {SpringConfig.class})
public class MainTest {
@Autowired
private AccountService accountService;
@Test
public void testQueryAccountById() throws Exception {
Account account = accountService.queryAccountById(1);
System.out.println(account);
}
}
```
读取xml配置文件启动的形式
```
// 使用Spring自定义的junit运行器替换它默认的运行器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定配置文件或者配置类
@ContextConfiguration(value = {"classpath:applicationContext.xml"})
public class JunitXmlTest {
@Autowired
private AccountService accountService;
@Test
public void testXml() throws Exception {
accountService.saveAccount(new Account());
}
}
```