控制反转IOC
在person和cleanAir这两个类中,person类依赖于cleanAir类。以往来说,我们是在person类里亲自去new一个cleanAir类的对象,
而这里,Person类不必自己去new,他只需要被动地接收cleanAir对象。这种被动接收依赖对象的依赖方式叫依赖注入。由主动new到被动接收的过程叫做控制反转。
但是这样设计类也有不足的地方。
假如这个类依赖的不再是cleanAir而是dirtyAir,那么就要再增加一个dirtyAir类,还要修改person类的代码。这种强依赖有很大的弊端,一处的变化引起其他地方的变化,而且改变的只是IAir,但是Person也要一起变。为了减少修改的地方,面向接口编程出现了。
这里定义了一个接口IAir,cleanAir和dirtyAir实现了IAir。Person类不再直接依赖CleanAir类,而是依赖IAir接口。这样当Person需要依赖dirtyAir对象时,无需修改代码,只要给他修改注入的对象。这个注入的过程,利用Spring框架只需要改一下配置即可实现。
IOC底层实现:
xml解析 工厂模式 反射
工厂模式:
IOC接口:
IOC思想基于IOC容器完成,IOC容器的底层是对象工厂
Spring提供IOC容器实现的两种方式:
(1)BeanFactory:IOC容器基本实现,是Spring内部实现的一个接口,不提供给(不建议)开放人员进行使用
(2)ApplicationContext:BeanFactory接口的子接口。提供了更多更强大的功能,一般是面向开放人员进行使用的。
IOC接口这个概念貌似只有尚硅谷提到了,是否有这个概念还有待商榷。
选中一个类按CTRL+H可以查看他的类结构
IOC容器--bean管理--xml方式 (这个方式太麻烦了,但是注解方式应该也是基于xml方式实现的,同样的原理,更简单的表达方式。为了更好地学习注解方式,也应当要学一下xml方式)
IOC容器--bean管理--注解方式
注解的基本格式:
@注解名称(属性名称=属性值,属性名称=属性值..)
注解可以作用在类,方法,属性上面。
创建bean对象:
在类上使用@Component @Service @Repository @Controller 可以创建bean对象。
其作用相当于在xml中配置:
<bean id="" class="com.company"></bean>
如果不添加属性的话,注解生成的bean对象,其id就是类名称首字母小写形式。
也可以@Component(value="")来指定id
这四个注解的功能都是一样的,只是语境不同,@Service用于Service层 ,@Repository用于dao层 ,@Controller用于Controller层,@Component应该是用于pojo层
使用注解是要开启组件扫描的,可以通过xml实现,也可以通过注解实现,个人喜欢完全注解开发,不希望有xml文件
完全注解开发:
创建一个配置类,在其上添加注解@Configuration以标识它是个注解类,
添加注解@ComponentScan(basePackages = {"com.company"}),以开启组件扫描,并指定扫描路径
关于@ComponentScan,要去了解他的属性,通过设置不同的属性,可以实现不同的扫描效果。
@Configuration @ComponentScan(basePackages = {"com.company"}) public class Config { }
使用注解注入属性
将依赖对象创建为bean对象后,我们是要去使用他的,所以下一步要进行依赖注入
注解关键字:
@Autowired:根据类型注入,但是,当一个接口有多个实现类时,就无法判断要注入哪一个实现类,所以要再使用@Qualifier以确定是哪一个实现类
@Qualifier:根据名称注入(即id,未设置情况下为类名称首字母小写形式),要与@Autowired一起使用
@Resource:可根据类型注入,也可根据名称注入
@Value:可以给普通类型(非对象类型)注入属性
以上注解在声明的类变量上面添加
每个注解的属性关键字是不同的,每次用就上百度查是不方便的,如何知道所用注解是如何定义的呢?
ctrl+鼠标点击即可实现
使用@Bean进行对象注册
Indicates that a method produces a bean to be managed by the Spring container.
@Bean注解是专用于方法上面的,如果一个方法返回了一个对象,并且在方法之上使用了@Bean,那么这个对象就被spring容器管理了
如果要使用这个对象,有三种依赖注入的方式
1.基于属性的依赖注入
@Component public class FieldBasedInjection { @Autowired private InjectedBean injectedBean; }
2.基于构造函数的依赖注入
@Component public class ConstructorBasedInjection { private final InjectedBean injectedBean; @Autowired public ConstructorBasedInjection(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
3.基于Setter的依赖注入
@Component public class SetterBasedInjection { private InjectedBean injectedBean; @Autowired public void setInjectedBean(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
spring目前不推荐使用基于属性的依赖注入,但不影响使用
什么情况下使用@Bean去注册bean对象而不是@Component之类的?
我认为,是在使用别人提供的类的时候,自己创建一个类的时候,我们可以自己在类上面加注解,但是别人的类,我们无法去修改,所以只能通过在返回对象的方法上面,加一个@Bean注解。
根据对IOC的理解,改下如下代码
成
用这种方法的话,必须的知道这个类的工厂代理类是什么,如果是我,我希望他们能够统一命名xxxFactory
这里创建对象的方法是静态方法,直接使用类去调用。
创建RestTemplate的类叫做RestTemplateBuider 创建的方法不是静态方法,需要由对象来创建
如何查看spring容器里现有的bean有哪些
1.在项目中引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
在application.properties配置文件里加上
management.endpoints.web.exposure.include=*
2.请求localhost:8080/actuator/beans,得到结果
3.复制结果到json格式化网站
就可以很直观地看到有没有你想看的bean了。
问题来了,为什么会有这么多不是我亲手注册的bean呢?
这里说,通过创建Application类可以定义一些关键bean
使用小技巧
可以导航到所使用的的依赖注册成bean的地方
可以定位到使用了这个bean对象的地方
本文来自博客园,作者:北征愚人,转载请注明原文链接:https://www.cnblogs.com/xukd/p/15101127.html