spring-ioc-1
1.IOC和ID的区别:
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。
其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)--->百度:JNDI
解释:IOC是程序所需要达到的目标
ID是实现IOC的技术手段
有点类似于orm->mabatis
2.依赖注入
(1)什么是依赖
A类中有个属性为B类,则称A依赖B
3.为什么要使用springioc
场景:1.我有N个类维护着List接口的实现这么一个属性,在传统情况下都是List list = new ArrayList();倘若现在业务需求发生了变化,需要变为List list = new LinkedList();name就需要修改N个类,
但是在有spring的情况下,我们只需要修改注入的类(xml方式,annotation方式)即可.
2.为service添加事务
好处:程序解耦合等等....
4.spring实现IOC的思路和方法
既然我们在类中已经定义了他们之间的依赖关系那么为什么还需要在配置文件中去描述和定义呢?
spring实现IOC的思路大致可以拆分成3点:
1.应用程序中提供类,提供依赖关系(属性或者构造方法)
2.把需要交给容器管理的对象通过配置信息告诉容器(xml、annotation,javaconfig)
3.把各个类之间的依赖关系通过配置信息告诉容器
5.spring编程的风格
-
schemal-based-------xml
-
annotation-based-----annotation
-
java-based----java Configuration
6.注入的两种方式
(1)Constructor-based Dependency Injection -----基于构造方法注入
(2)Setter-based Dependency Injection -----基于Set注入
7.自动装配
上面说过,IOC的注入有两个地方需要提供依赖关系,一是类的定义中,二是在spring的配置中需要去描述。自动装配则把第二个取消了,即我们仅仅需要在类中提供依赖,继而把对象交给容器管理即可完成注入。
在实际开发中,描述类之间的依赖关系通常是大篇幅的,如果使用自动装配则省去了很多配置,并且如果对象的依赖发生更新我们可以不需要去更新配置,但是也带来了一定的缺点
自动装配的优点参考文档:
缺点参考文档:
<bean id="A" class="com.cg.A"> </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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd default-autowire="byName">
指定自动装配的方式,通常使用byName,byTtype
如果有个别类需要特殊处理则可以通过以下方式进行处理
<bean id="A" class="com.cg.A" autowire="byName">
<!--设置装配的方式-->
</bean>
8.springBean的作用域
singleton |
(Default) Scopes a single bean definition to a single object instance for each Spring IoC container. |
prototype |
Scopes a single bean definition to any number of object instances. |
PS:倘若存在单例Service,其内部维护着作用域为prototype的Dao,那么从spring容器中获取Service对象中的dao是否是多例的???
测试:
Dao:
@Repository @Scope(value = "prototype")
//配置多例 public class IndeDaoImpl implements IndexDao { @Override public void get() { System.out.println("dao"+this.hashCode()); } }
Service:
@Service
//默认单例 public class IndexServiceImpl implements IndexService { @Autowired private IndexDao indexDao; @Override public void get() { indexDao.get(); } }
Test:
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); IndexService bean1 = ac.getBean(IndexService.class); bean1.get(); IndexService bean2 = ac.getBean(IndexService.class); bean2.get();
console:
dao1195067075
dao1195067075
由实例表明:
service单例,dao多例的情况,获取service中的dao依旧是单例的.
原因:
spring只对Singleton范围的对象初始化一次.......
解决方案:
参考官方文档:
方案一:
A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface,
and by making a getBean("B") call to the container ask for (a typically new) bean B instance every time bean A needs it. The following example shows
this approach:
一种解决办法是放弃某种反向控制。您可以通过实现applicationcontext - ware接口
,以及在bean A每次需要bean B实例时对容器发出getBean(“B”)调用来让bean A知道容器。
下面的例子展示了这种方法:
修改Service:
@Service public class IndexServiceImpl implements IndexService,ApplicationContextAware { /* @Autowired private IndexDao indexDao;*/ private ApplicationContext ac; @Override public void get() { /*indexDao.get();*/ IndexDao bean = ac.getBean(IndexDao.class); bean.get(); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.ac = applicationContext; } }
test:
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); IndexService bean1 = ac.getBean(IndexService.class); bean1.get(); IndexService bean2 = ac.getBean(IndexService.class); bean2.get();
console:
dao306206744
dao827084938
结果显示:
dao为多例,测试成功----->由此引申出applicationContextAware接口的实现了有什么用,上例子很好的展示了此接口的用法!!!!
方案二:
通过@lookup注解
@Service public abstract class IndexServiceImpl implements IndexService{ @Override public void get() { IndexDao indexDao = createIndexDao(); indexDao.get(); } @Lookup()
protected abstract IndexDao createIndexDao(); }
console:
dao2038148563
dao2008966511
也可以通过注解的方式,笔者就不在此演示.
PS:如有错误,请指正!谢谢
github:https://github.com/897800754/myLearn/tree/master/springscope