栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring框架核心机制IOC和AOP深入解读spring基础

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring框架核心机制IOC和AOP深入解读spring基础

1. Spring框架 1.1 Spring简介
  • Spring就是分层的JavaSE应用full-strack轻量级开源框架,IOC(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)
  • 什么是轻量级?一般情况下如果框架api使用比较简单,就叫轻量级
1.2 Spring的架构组成
1.2.1 Spring框架

最重要的核心容器Core Container:分为4个部分

  • Beans ,容器主要放的就是定义的bean对象
  • Core,核心
  • Context,上下文
  • SpEL,就是Spring的EL表达式
1.2.2 工厂
  1. CoreContariner核心容器,其实是搭建并管理了工厂
  2. 是工厂的设计模式
  3. 工厂中是用来生产项目中一个一个的对象
  4. 因此使用spring最重要的就是搭建工厂
  5. 该工厂加载配置文件:.xml文件,生产配置中记录的对象,我们通过getBean方法调用就可以了
1.3 控制反转
1.3.1 例题讲解

什么是反转控制? 反转了依赖关系的满足方式,由之前的直接创建依赖对象,变为由工厂推送。(变主动为被动,即反转)解决了具有依赖关系的组件之间的强耦合

举例说明

  • 比如UserServiceImpl强耦合了UserDaoImpl,利用了反转控制,可以使UserServiceImpl不再引用任何一个UserDao的实现类例如UserDaoImpl,在需要UserDaoImpl的位置,我们只给一个属性UserDao userDao;并定义set/get方法,允许userDao属性接收spring赋值
public class UserServiceImpl implements UserService{

	private UserDao userDao;
    @Override
    public List queryUser() {
    	userDao.queryUser();
        return list;
    }
    public UserDao getUserDao(){
    	return UserDao;
    }
    public void setUserDao(UserDao userDao){
    	this.userDao = userDao;
    }
}
1.3.2 先写一个spring-context.xml文件
  • 上面我们说过了,反转控制,那么spring是怎么给UserServiceImpl类的UserDao属性赋值的呢?假设我们赋值的是UserDao的实现类UserDaoImpl
  • 首先,我们在.xml配置文件中定义一个标签,里面写
  • 标签的id随便给,id=“userDaoImpl”、class=”com/lyx/dao/impl/UserDaoImpl“,就是UserDaoImpl的路径

1.3.3 controller层

Control层调用Sevice层的时候,如下调用

        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
        UserDaoImpl userDao = (UserDaoImpl)context.getBean("userDaoImpl");
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(userDao);
        userService.queryPerson();

运行结果:这里成功调用了UserDaoImpl;

理解说明

  • Spring框架加载这个.xml配置文件,
  • 怎么加载?ClassPathXmlApplicationContext类加载
 ApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
  • ClassPathXmlApplicationContext 是ApplicationContext接口的实现类,它是从类的根路径下加载配置文件

  • ApplicationContext接口,它代表应用上下文,可以通过它的实例获得Spring容器中的Bean对象

  • 我们通过.getBean(”userDaoImpl“)生产对象

  • getBean()方法的参数给bean的id,返回的就是UserDaoImpl类型的对象,类型自己强转就行了

//Object userDaoImpl = context.getBean("userDaoImpl");
UserDaoImpl userDaoImpl = (UserDaoImpl)context.getBean("userDaoImpl");
  • getBean方法的参数也可以是Class类型,这样就不需要强转了,因为你已经告诉它了,但是这种方法只适合只有一个UserDaoImpl,如果还有一个会报错
UserDaoImpl userDaoImpl = context.getBean(UserDaoImpl.class);
  • 当然了,实现功能要先导Spring开发的基本包的坐标:Spring框架用到依赖
  • 还有一点,.xml在项目加载的时候不会被编译到target测试文件里面,需要在pom.xml里面配置一个
  
        
            
                src/main/java
                
                    *.xml
                    **/*.xml
                
                true
            
        
    
1.3.4 .xml配置文件的bean标签
    

id、class上面说过了
scope

  1. singleton单例
  2. prototype多例

init-method

  1. 在class定义的包.类里面定义的初始化方法

destroy-method

  1. 在class定义的包.类里面定义的销毁方法,
  2. 后台自动执行销毁方法,要手动.close才能看见销毁方法有没有执行
        ApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
        Object userDao = context.getBean("userDao");
        ((ClassPathXmlApplicationContext)context).close();//强转为ApplicationContext子类
2. Spring配置文件 2.1 依赖注入之Set注入
  • 在Spring创建对象的同时,为其属性赋值,我们称为依赖注入
  • 上面讲解反转控制的时候我们在UserServiceImpl中定义了userDao属性的get/set方法,
public class UserServiceImpl implements UserService{

	private UserDao userDao;
    @Override
    public List queryUser() {
    	userDao.queryUser();
        return list;
    }
    public UserDao getUserDao(){
    	return UserDao;
    }
    public void setUserDao(UserDao userDao){
    	this.userDao = userDao;
    }
}
  • 在调用userServiceImpl的时候我们是getBean返回了userDao,并通过set方法赋值给userServiceImpl的userDao属性,才成功调用
public class Controller{
	public static void main(String[] args){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
        UserDaoImpl userDao = (UserDaoImpl)context.getBean("userDaoImpl");
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(userDao);
        userService.queryPerson();
	}
}
  • 现在来用依赖注入
  • 直接getBean返回userServiceImpl对象
  • 我们在.xml文件中创建userServiceImpl对象的bean同时,为其属性userDao赋值
  • 配置在一个标签中
  • 这就是依赖注入


                           
    
    
        
    
 

  • 以后直接如下代码调用ServiceImpl类的方法
public class Controller{
	public static void main(String[] args){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
        UserServiceImpl userServiceImpl = (UserServiceImpl)context.getBean("userServiceImpl");
        userServiceImpl.queryPerson();
	}
}
  • 对比一下之前的
public class Controller{
	public static void main(String[] args){
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring-context.xml");
        UserDaoImpl userDao = (UserDaoImpl)context.getBean("userDaoImpl");
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(userDao);
        userService.queryPerson();
	}
}
  • 以上代码在UserServiceImpl类中没有强耦合,我们把它所有要用到的对象,如userDaoImpl,都放到了容器中,spring搭建并管理工厂,工厂加载配置文件.xml文件,生产配置文件中记录的Bean对象

以上依赖注入中的property标签也可以简化

   

    
    


2.2 依赖注入之构造注入

和以上差不多,只不过property标签换成了constructor-arg标签 该标签的name值为你当前bean的class值中类的构造方法的参数类型,ref的值就是的id值

   

    
    //set注入:2中方式
    //方式1
    
    //方式2
    
        
    
    
    //构造注入
    
        
    


当然了,UserServiceImpl类中要有构造方法

 public userServiceImpl(userDaoImpl userDao) {
}
2.3 依赖注入之注入数据类型,set注入
  • 以上注入都是把Dao注入给Service
  • 除了对象的引用可以注入,普通数据类型,集合等到可以在容器中注入
  • 比如Person类中的属性如下,有jdk8种数据类型,数组,集合,自建的Address类 ,有构造方法
  • 注入实现如下

2.3.1 Person类
public class Address {
    private int id;
    private String city;
    
    public int getId() {return id; }
    public void setId(int id) {this.id = id;}
    public String getCity() {return city;}
    public void setCity(String city) { this.city = city;}
}

package com.lyx.entity;

import com.sun.xml.internal.ws.wsdl.writer.document.http.Address;

import javax.swing.*;
import javax.xml.ws.soap.Addressing;
import java.util.*;

public class Person {
    //基本数据类型
    private int id;
    private String name;
    private Date bornDate;
    //数组
    private String[] hobbys;
    //集合
    private Set phones;
    private List names;
    private Map contries;
    //文件
    private Properties files;
    //自建类型
    private Address address;

    public int getId() { return id; }

    public void setId(int id) {this.id = id;}

    public String getName() {return name;}

    public void setName(String name) {this.name = name;}

    public Date getBornDate() {return bornDate;}

    public void setBornDate(Date bornDate) {this.bornDate = bornDate;}

    public String[] getHobbys() {return hobbys;}

    public void setHobbys(String[] hobbys) {this.hobbys = hobbys;}

    public Set getPhones() {return phones;}

    public void setPhones(Set phones) {this.phones = phones;}

    public List getNames() {return names; }

    public void setNames(List names) {this.names = names;}

    public Map getContries() { return contries;}

    public void setContries(Map contries) {this.contries = contries;}

    public Properties getFiles() {return files;}

    public void setFiles(Properties files) {this.files = files;}

    public Address getAddress() {return address;}

    public void setAddress(Address address) {this.address = address;}

    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", bornDate=" + bornDate +
                ", hobbys=" + Arrays.toString(hobbys) +
                ", phones=" + phones +
                ", names=" + names +
                ", contries=" + contries +
                ", files=" + files +
                ", address=" + address +
                '}';
    }
}

2.3.2 person-context.xml配置文件


    
        
        
    
	

    
    
    
    
    
        
            football
            basketball
        
    
    
    
        
            111
            222
        
    
    
        
            tom
            jack
        
    
    
        
            
            
        
    
    
        
            jdbc:mysql:xxx
            root
        
    
    
    
	

2.4 引入其他配置文件



    
    

3. Spring配置数据源
  • 连接池可以用C3P0、我用的是Druid

jdbc.properties

jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3308/companydb?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
jdbc.init=1
jdbc.minIdle=1
jdbc.maxActive=20


    
    
    
        
        
        
        
        
        
        
        
    
   

4. Spring注解开发
4.1 原始注解

注解开发主要是代替的配置,对于我们注解的类或者属性,.xml文件配置一个组件扫描,spring把注解了的类自动放入容器中


注解说明
@Component
@Autowired和@Qualifier(”“)
@Repository
@Value
@Scope(“”)
@PostConstruct
@PreDestroy
4.1.1注解说明

Dao和Service的bean配置原始代码如下

    
    
        
    
  • 对于上面DaoImpl的配置,用注解代替,直接到bean的class的包的类下面,也就是这个userDaoImpl类,添加一个@Component(”“),里面的参数就是上面bean的id
  • ServiceImpl的配置,同上,但因为有依赖注入,我们还要用@Autowired和@Qualifier(”“),Qualifier里面参数是上面ref的值
  • 注解加完了,在.xml文件配置组件扫描
  • com.lyx是扫描这个路径下面所有的包
  • 注意这里用到了context,记得在beans属性里面加.xsd路径

  • 以下是完整代码
@Component("userDaoImpl")
public class UserDaoImple implements UserDao{
	@Override
	public List queryUsers(){
		sql语句和queryRunner.query(sql)
	}
}
@Component("userServiceImpl")
public class UserServiceImpl implements UserService{
	@Autowired
	@Qualifier("userDaoImpl")
	private UserDao userDao;
	public void setUserDao(UserDao userDao){
		this.userDao = userDao;
	}
	public List queryUsers(){
		userDao.queryUsers();
	}
}


   
   

其他注解如下


  1. 对于以上的@Component,不方便区分dao层还是Service层亦或者是Controller层
  2. 所以对于本来要使用@Component的位置,我们在Dao层用@Repository,在Service层用@Service,在Controller层用@Controller
  3. 对于上面使用的@Autowired和@Qualifier(" ")我们可以合并成一个@Resource(name= " ")
  4. @Value注入普通属性,可以通过@Value(”${ jdbc.driver}“)获取jdbc.properties文件的值,赋值给添加这个注解的变量,jdbc.properties必须在.xml配置文件中被放入容器中
@Vaule("${jdbc.driver}")
private String driver;//driver=
  1. @Scope(“”)标志Bean的作用范围,单例、多例,值为prototype和singleton
  2. @PostConstruct,使用在方法上,标注该方法是Bean的初始化方法,类似于init-method
  3. @PreDestroy,使用在方法上,标注该方法是Bean的摧毁方法,类似于destroy-method

4.2 新注解

以上原始注解,不能全部替代xml配置文件的Bean在例如连接池这种Bean中,我们不能到它的包.类去添加注解,包括组件扫描,也扫描不了

注解说明
@Configuration用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解
@ComponentScan用于指定Spring在初始化容器时哟啊扫描的包,作用和Spring的xml配置文件中的一样
@Bean使用在方法上,标注将该方法的返回值存储到Spring容器中 ,如@Bean(“dataSource”),Spring会将当前方法的返回值以指定名称(dataSource)存储到Spring容器中
@PropertySource用来加载.properties文件中的配置,作用和Spring的xml配置文件中的 一样
@Import用于导入其他配置文件,作用和Spring的xml配置文件中的一样,@Import({XXX.class,XXX.xml})可以导入多个配置文件
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/837142.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号