Spring的IOC

IOC即控制反转,即反转了创建对象的权利,DI即依赖注入,两者其实是同一概念只是角度不同。

IOC

依赖注入一般有三种方式:构造注入、setter注入、注解注入。接下来依次讲解这三种注入方式:

构造注入:

通过构造方法将所需属性注入进来

application.xml

1         <!-- 构造注入 -->
2     <bean id="ball" class="priv.cq.implBall.PingPangBall"></bean>
3         
4     <bean id="english" class="priv.cq.implPerson.English">
5         <constructor-arg ref = "ball" />
6     </bean>

有两个接口:IPerson、IBall分别代表不同国家和不同球类运动,有实现类类PingPangBall、English,意在得到English对象,然后调用其内playGameing()方法,该方法内部调用了PingPangBall的desc()方法。那么现在就要完成两件事,一是创建English对象,二是将PingPangBall对象的实例注入进去。传统模式下创建对象直接通过new Object()完成,但spring的IOC是通过加载配置文件来完成的:

Test

 1 public class Test {
 2     public static void main(String[] args) {
 3         @SuppressWarnings("resource")
 4         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
 5         IPerson person0 = (IPerson) ctx.getBean("english");
 6         
 7         System.out.print("英国人说:");
 8         person0.playGameing();
 9     }
10 }

如4、5行所示通过给一个配置文件得到bean,该bean的id是唯一存在的。

English

 1 public class English implements IPerson{
 2     
 3     private IBall ball;
 4     
 5     public English(IBall ball) {
 6         this.ball = ball;
 7     }
 8     @Override
 9     public void playGameing() {
10         ball.desc();
11     }
12 }

PingPangBall

1 public class PingPangBall implements IBall {
2 
3     @Override
4     public void desc() {
5         System.out.println("乒乓球是很具魅力的运动!");
6     }
7 
8 }

setter注入:

通过set方法将所需属性注入进来

application.xml

 

1         <!-- setter注入 -->
2     <bean id="chinese" class="priv.cq.implPerson.Chinese">
3         <property name="ball" ref="ball" />
4     </bean>

 

Chinese

 1 public class Chinese implements IPerson {
 2 
 3     private IBall ball;
 4 
 5     public void setBall(IBall ball) {
 6         this.ball = ball;
 7     }
 8 
 9     @Override
10     public void playGameing() {
11         ball.desc();
12     }
13 }

Test

 

 1 public class Test {
 2     public static void main(String[] args) {
 3         @SuppressWarnings("resource")
 4         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
 5         IPerson person0 = (IPerson) ctx.getBean("english");
 6         
 7         System.out.print("英国人说:");
 8         person0.playGameing();
 9         
10         IPerson person1 = (IPerson) ctx.getBean("chinese");
11         
12         System.out.print("中国人说:");
13         person1.playGameing();
14     }
15 }

注解注入:

通过注解的方式注入属性。

application.xml

        <!-- spring会自动扫描xxx路径下的注解。 -->
    <context:component-scan base-package="priv.cq"></context:component-scan>

        <!-- 注解注入 -->
    <bean id="japanese" class="priv.cq.implPerson.Japanese" />

注意,使用注解注入的时候,记着要加包扫描的标签,这样我们使用的注解才能起到作用,否则注解是无效的 ,因为容器没有识别出!

Japanese

 1 public class Japanese implements IPerson{
 2     
 3     @Autowired
 4     private IBall ball;
 5     
 6     @Override
 7     public void playGameing() {
 8         ball.desc();
 9     }
10 }

Test

结果如上

其实还可以直接用service注解完成控制反转,不用任何配置文件。

UserService

 1 @Service
 2 public class UserService implements IPerson{
 3     @Autowired
 4     private IBall ball;
 5 
 6     @Override
 7     public void playGameing() {
 8         ball.desc();
 9     }
10 }

spring会根据该注解自动生成UserService的实例,bean的id默认是该类名的首字母小写,即userService。也可以自己指定bean的id:@Service("suibian")。

自己实现的简易ioc

原则:通过包扫描先扫描到带有自定义的@ComponentScan注解,然后进一步判断该类是否含有@Bean注解的方法,如果有,那么该类就是创建对象的类,该方法就是创建对象的方法。维护一个工厂类,提供一个map集合,该集合存放bean的id和bean的实例。扫描到创建对象的方法后,通过反射机制动态执行该方法生成实例,加入到工厂的map集合中。该工厂类提供一个getBean()方法供外界获取实例。使用的时候只需要用工厂实例调用getBean(“String id”)即可。当我们需要使用别的对象时,只需要添加配置类即可,即带有@ComponentScan注解的类以及带有@Bean注解的方法。

下面是我自己简单实现的ioc,感兴趣的朋友可以看看,多多指正交流

https://files.cnblogs.com/files/mvcq/20180528%40%E5%B7%A5%E5%8E%82%E4%BA%A7%E7%94%9F%E4%B8%80%E4%B8%AAbean.rar

 

posted @ 2018-06-19 16:53  我能摸到光  阅读(253)  评论(0)    收藏  举报