spring之IOC实现的其他方式

Posted 头发浓密似羊毛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring之IOC实现的其他方式相关的知识,希望对你有一定的参考价值。

在上一个博客中我们讲解了spring的对象获取和成员变量属性的注入方式;现在我们来讲解不适用配置文件而是直接在java中直接配置,这也是在springBoot流行之后,利用java类配置来取代xml文件配置的一种方式。

java类取代xml配置的详解:

第一java配置需要引入的jar包:

第二:创建一个java类

在创建的java类中有两个注解要注意不要忘记:

一个是configuration;另一个是Bean。还要注意这两个注解所代表的意思

/**
 *
 */
package com.sxt;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author ASUS
 * 这是java的工具类来取代application.xml:
 * 第一步:在该java类中添加一个注解configuration;注意这个注解所在的包;这一步加了注解就相当于application.xml
 * 中只有<beans>这个标签内的内容是一样的
 *
 */
@Configuration
public class javaConfig {
    /**
     * 这里也要加一个注解Bean,这里的注解就相当于在application.xml中的<bean class="com.sxt.Person /">一样
     * 而且这里还可以给一个别名
     * @return
     */
    @Bean("a1")//这是给的别名
    Person getPerson() {
        return new Person();
        
    }
}
第三:创建一个实体类

/**
 *
 */
package com.sxt;

import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author ASUS
 *
 */
public class Person {
    private int age;
    private String name;
    //private Cat cat;
    
    //private Map<String, Object> map;
    
    private Properties properties;
    
    @Override
    public String toString() {
        return "Person [age=" + age + ", name=" + name + ", properties=" + properties + "]";
    }
    public Person() {
        System.out.println("我是无参构造!!");
    }
    //使用构造注入必须有带参构造方法
    /*public Person(int age,String name) {
        this.age=age;
        this.name=name;
    }*/
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void say() {
        System.out.println("hello>>>>");
    }
    /**
     * @return the properties
     */
    public Properties getProperties() {
        return properties;
    }
    /**
     * @param properties the properties to set
     */
    public void setProperties(Properties properties) {
        this.properties = properties;
    }   
}
第四:在测试类可以看到

值得注意的是:(1)获取类对象的方法已经改变:ClassPathXmlApplicationContext变成了AnnotationConfigApplicationContext

(2)这个时候不需要配置文件application.xml

(3)需要在java类中添加两个注解了

(4)注解可以添加别名:通过别名也能获取类对象

利用spring解耦类之间的关系的通过设值注入的方式来简单的实现服务器dao,service,controller之间对象调用:

第一创建三个层之间的一个简单的方法;来模拟他们之间的调用关系:这里用到的是对象的设值注入

代码如下:

dao 层:

/**
 *
 */
package com.sxt.dao;

/**
 * @author ASUS
 *
 */
public interface IUserDao {
    public String add();

}
dao的实现层:

/**
 *
 */
package com.sxt.daoimpl;

import com.sxt.dao.IUserDao;

/**
 * @author ASUS
 *
 */
public class UserDaoImpl implements IUserDao {

    @Override
    public String add() {
        // TODO Auto-generated method stub
        return "hahaha...";
    }

}
service层:

/**
 *
 */
package com.sxt.service;

/**
 * @author ASUS
 *
 */
public interface IUserService {
    public String add();

}
service的实现层:

/**
 *
 */
package com.sxt.serviceimppl;

import com.sxt.dao.IUserDao;
import com.sxt.daoimpl.UserDaoImpl;
import com.sxt.service.IUserService;

/**
 * @author ASUS
 *
 */
public class UserServiceImpl implements IUserService {
    //在学习了spring框架之后的做法;这是某个类对象
    private IUserDao dao;
    public void setDao(IUserDao dao) {
        this.dao = dao;
    }
    @Override
    public String add() {
        // TODO Auto-generated method stub
        return dao.add();
    }
    /* //在没有实现spring框架之前的做法
    private IUserDao dao=new UserDaoImpl();
    @Override
    public String add() {
        // TODO Auto-generated method stub
        return dao.add();
    }
*/
}
controller层:

/**
 *
 */
package com.sxt.controller;

import com.sxt.service.IUserService;

/**
 * @author ASUS
 *
 */
public class UserController {
    private IUserService service;
    
    public void setService(IUserService service) {
        this.service = service;
    }

    public String add() {
        return service.add();
        
    }
    
}
配置文件:

<bean class="com.sxt.daoimpl.UserDaoImpl" id="userimpl"/>
 <bean class="com.sxt.serviceimppl.UserServiceImpl" id="serviceimpl">
 <property name="dao" ref="userimpl"></property>
 </bean>
 <bean class="com.sxt.controller.UserController">
 <property name="service" ref="serviceimpl"></property>
 </bean>

测试类:

但是,我们会发现一个问题,那就是配置文件中代码太多了,不方便管理;所以我们要知道自动配置。

第一步:添加扫描路径:需要扫描的类必须在指定的路径中,如果不在的话会报错;在这里要在namespace中选择context;这种扫描是一种范围的扫描,只要在该包下的类都会被扫描

第二步:在相关类加一个component注解;这样就不用去配置文件注释了。

第三步:直接测试

将上面的案例的配置文件的修改成自动配置

然后在响应的三个类中添加两个注解:

/**
 *
 */
package com.sxt.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.sxt.service.IUserService;

/**
 * @author ASUS
 *
 */
@Component//表示将注解交给spring容器管理
public class UserController {
    @Autowired//表示spring容器在实例化的时候会自动到配置文件中给对应的对象赋值
    private IUserService service;
    public String add() {
        return service.add();
    }
}
注意这两个注解的不同之处;此外这里的类注解一定有四个

@Component:一般用在身份不明确的组件上

@Controller:用在controller层

@Service:用在service层

@Repository:用在数据库访问层

利用java类来代替配置文件的扫描

/**
 *
 */
package com.sxt;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author ASUS
 *
 */
@Configuration
//添加扫描注解
@ComponentScan("com.sxt.bean")//多个扫描路径同样逗号隔开
public class javaConfig {
 
}
Profile:

在实际的工作中,在项目上线之前,可能需要不挺的在不同的测试环境中切换,

模拟DataSource:

/**
 *
 */
package com.sxt;

import javax.xml.crypto.Data;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import com.sxt.bean.DataSource;

/**
 * @author ASUS
 *
 */
@Configuration
public class javaConfig {
    @Bean
    @Profile("dev")
    public DataSource devDs() {
        return new DataSource("192.168.121.2","root", "123");    
    }
    @Bean
    @Profile("test")
    public DataSource testDs() {
        return new DataSource("192.168.142.3","admin", "admin");
    }
    

}
java类:

/**
 *
 */
package com.sxt;

import javax.xml.crypto.Data;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import com.sxt.bean.DataSource;

/**
 * @author ASUS
 *
 */
@Configuration
public class javaConfig {
    @Bean
    @Profile("dev")
    public DataSource devDs() {
        return new DataSource("192.168.121.2","root", "123");    
    }
    @Bean
    @Profile("test")
    public DataSource testDs() {
        return new DataSource("192.168.142.3","admin", "admin");
    }
    

}
测试类:

/**
 *
 */
package com.sxt;


import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.sxt.bean.DataSource;



/**
 * @author ASUS
 *
 */
public class Test01 {
    public static void main(String[] args) {
        //获取对象:方法一
        AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(javaConfig.class);
        //动态切换环境
        ac.getEnvironment().setActiveProfiles("dev");
        ac.register(javaConfig.class);
        ac.refresh();
        DataSource ds = ac.getBean(DataSource.class);
        System.out.println(ds);
        
    }

}
这个也可以中配置文件的方式:

 <beans profile="dev">
 <bean class="com.sxt.DataSource">
<constructor-arg name="url" value="192.168.121.3"/>
<constructor-arg name="username" value="root"/>
<constructor-arg name="password" value="123"/>
</bean>
</beans>
<beans profile="test">
 <bean class="com.sxt.DataSource">
<constructor-arg name="url" value="192.168.121.2"/>
<constructor-arg name="username" value="admin"/>
<constructor-arg name="password" value="123"/>
</bean>
</beans>

测试类中:

ClassPathXmlApplicationContext ac=new ClassPathXmlApplicationContext("application.xml");
        ac.getEnvironment().setActiveProfiles("dev");
        ac.refresh();
        DataSource bean = ac.getBean(DataSource.class);
        System.out.println(bean);

 

以上是关于spring之IOC实现的其他方式的主要内容,如果未能解决你的问题,请参考以下文章

spring之IOC

Spring知识点总结之注解方式实现IOC和DI

Spring之IOC-注解方式

长文预警!Spring源码之IoC容器的基本实现

Spring5源码分析(004)——IoC篇之理解Ioc

Spring框架的IOC之注解方式的快速入门