1 spring概述

spring是分层的JavaSE及JavaEE应用于全栈的轻量级开源框架,以 IoC (Inverse Of Control:控制反转/反转控制)和 AOP (Aspact Oriented Programming:面向切面编程)为核心,提供了表现层SpringMVC和持久层Spring JDBC以及业务层事务管理等众多模块的企业级应用技术,还能整合开源世界中众多 著名的第三方框架和类库,逐渐成为使用多的JavaEE企业应用开源框架。

spring框架主要用来处理业务间的逻辑,如账号注册时的用户名判断等等。

spring框架其中最核心的是:IoC控制反转、DI依赖注入、SpringAOP面向切面编程、事务控制。

1.1 spring的架构:

Spring 初的目标就是要整合一切优秀资源,然后对外提供一个统一的服务。 Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式, 如下图所示:
image.png
组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多 个模块联合实现。每个模块的功能如下:
image.png

2 IoC+DI

IoC是设计思想,IoC有三个核心:BeanFactory、反射、DI。BeanFactory利用反射实现对象的创建,DI实现对象关系管理。

2.1 IoC控制反转

IOC(Inverse Of Control)控制反转,即,把创建对象的权利交给框架。
也就是指将对象的创建、对象的存储、对象的管理交给了spring容器。
image.png

2.1.1 spring中的IoC的实现

第一步:创建maven项目spring
image.png
第二步:在pom文件中添加junit、spring依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.1.3.RELEASE</version>
        </dependency>

第三步:在工程的src/main/resources目录下,创建applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 将EmpService接口的实现类作为bean注册到spring容器中
        即 让spring容器创建该类的实例(对象)
        如果注册的类有父接口,id值通常是接口名(首字母小写)
        如果注册的类没有父接口,id值通常为类名(首字母小写) -->
    <bean id="empService" class="com.tedu.service.EmpServiceImpl02"></bean>
    
    <!-- 将User类作为bean注册到spring容器中, 也就是由spring容器
        负责创建该类的实例 
        scope="singleton|prototype",默认值是singleton,表示单实例
        如果将scope值改为prototype,则每次都会创建新的User实例,也就
        是多实例 -->
    
    <!-- (2)构造方法注入 -->
    <bean id="user" class="com.tedu.pojo.User">
        <constructor-arg name="name" value="马云"/>
        <constructor-arg name="age" value="30"/>
        <constructor-arg name="info" ref="userInfo"/>
    </bean>
    
    
    <!-- 将UserInfo类作为bean注册到spring容器中 -->
    <bean id="userInfo" class="com.tedu.pojo.UserInfo"></bean>
    
</beans>

第四步:创建测试类TestSpring,进行测试

package com.tedu;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.tedu.pojo.User;

public class TestSpring {
    //获取spring的容器对象
    ClassPathXmlApplicationContext ac = 
            new ClassPathXmlApplicationContext(
                    "applicationContext.xml");

    @Test
    public void testIoC() {
        //通过spring容器对象获取User类的实例
        User u1 = (User)ac.getBean("user");

}

2.1.2 springboot整合spring中的IoC的实现

实现类上加注解@service,将时间类交给spring框架管理,放入bean容器。
利用@Autowired注解,由框架进行对象赋值。

第一步:创建UserService

package com.tedu.springioc01.service;

public interface UserService {
    public String register();
}

第二步:创建UserServiceImpl实现UserService

package com.tedu.springioc01.service;

import org.springframework.stereotype.Service;

//这是一个业务层类,由框架创建对象
@Service
public class UserServiceImpl implements UserService{

    @Override
    public String register() {
        //判断用户名是否注册过
        return "注册成功";
        
    }
}

第三步:创建UserController

@RestController
public class UserController {

//由框架给userService赋值,不用程序员创建
    @Autowired
    UserService userService;

    @RequestMapping("/register")
    public String register() {
        String result=userService.register();
        return result;
    }
}

2.1.3 springboot整合spring中的IoC的底层实现

image.png
第一步:创建注解自定义Autowired

package org.spring.ioc;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

//自动装配,给属性自动赋值
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {

}

第二步:创建UserServiceImpl

package com.tedu;
//业务层类
public class UserServiceImpl {

}

第三步:创建UserController

package com.tedu;
//表现层

import org.spring.ioc.Autowired;

public class UserController {
//需要业务层对象
    @Autowired
    UserServiceImpl userServiceImpl;
}

第四步:创建IOCMain,模拟spring框架

  • 创建LoadObject()容器。
  • 在autowiredProcess()中通过反射处理autowired,给属性赋值。
package org.spring.ioc;
//模拟spring 框架

import java.awt.Container;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Set;

import com.tedu.UserController;
import com.tedu.UserServiceImpl;

public class IOCMain {
//放对象的容器
    public static HashMap<String, Object> container=new HashMap<String, Object>();
    //userServiceImpl,object
    //userController,UserController的对象
    public static void main(String[] args) throws Throwable {
        //加载对象到容器中
        loadObject();
        //处理autowired,给属性赋值
        autowiredProcess();
        //测试UserController的userServiceImpl属性是否有值
        //从容器中找对象
        UserController userController=(UserController) 
                container.get("userController");
        //打印对象的属性
        System.out.println(userController.toString());
    }
    private static void autowiredProcess() throws Throwable{
//遍历hashMap的key
        Set<String> keySet=container.keySet();//得到集合
        for (String name : keySet) {
            //根据key得到对象
            Object object=container.get(name);
            //根据对象得到类对象
            Class clazz=object.getClass();
            //根据类对象得到所有属性
            Field[] fields=clazz.getDeclaredFields();
            //遍历所有属性
            for (Field field : fields) {
                //判断属性是否加了autowired
                Autowired autowired=field.getAnnotation(Autowired.class);
                //如果加了,给容器中找到对象,赋值
                if (autowired !=null) {
                    //field.getName() userServiceImpl
                    Object value=container.get(field.getName());
                    field.setAccessible(true);
                    //创建对象
                    field.set(object, value);
                }
            }
        }
    }
    private static void loadObject() {
        UserController userController=new UserController();
        container.put("userController",userController);
        
        UserServiceImpl userServiceImpl=new UserServiceImpl();
        container.put("userServiceImpl",userServiceImpl);    
    }    
}

2.2 DI依赖注入

Set方法注入:

<bean id="user" class="com.tedu.spring.User">
    <property name="name" value="韩少云"/>:调用setName方法给name属性赋值为韩少云
    <property name="age" value="20"/>:调用setAge方法给age属性赋值为20
    <property name="info" ref="userInfo"/>
</bean>
<!--调用setInfo方法给info属性赋值为UserInfo类型的对象
上面的ref属性指向的是,在获取UserInfo类的对象时bean标签的id值-->

构造方法注入:

<bean id="user" class="com.tedu.pojo.User">
    <constructor-arg name="name" value="马云"/>
    <constructor-arg name="age" value="30"/>
    <constructor-arg name="info" ref="userInfo"/>
</bean>

注解@Autowired注入

AOP

AOP面向切面编程,AOP是对动态代理的封装。
image.png
切面类=切入点(ponitcut())+通知方法(@Around+@Before+@AfterReturning+@AfterThrowing)

静态代理

image.png
第一步:创建接口IDAO

public interface IDAO {
    public void insert();
}

第二步:创建实现类UserDao实现IDAO

//目标类
public class UserDAO implements  IDAO {
    @Override
    public void insert() {
        System.out.println("目标类UserDAO 的核心代码 insert");
    }
}

第三步:创建代理类Proxy并添加业务功能

//代理类的方法必须和目标类的方法一致
public class Proxy implements IDAO {
    IDAO target;

    public Proxy(IDAO target) {
        this.target = target;
    }

    @Override
    public void insert() {
        long startTime = System.nanoTime();
        target.insert();
        long endTime = System.nanoTime();
        System.out.println("insert占用的时间=" + (endTime - startTime));

    }
}

第四步:测试静态代理

public class TestProxy {
    public static  void  main(String[] args){
        //创建目标对象
        IDAO userDAO=new UserDAO();
        //得到代理对象
        Proxy userDAOproxy=new Proxy(userDAO);
        //调用代理的方法
        userDAOproxy.insert();       
    }
}

动态代理

第一步:创建IDAO接口

package springaop04_javaDynamicProxy;

public interface IDAO {
    public String select(String username);
}

第二步:创建实现类UserDAO实现IDAO

package springaop04_javaDynamicProxy;
public class UserDAO implements IDAO{
    @Override
    public String select(String username) {
        return "目标类UserDAO.select()"+username;
    }
}

第三步:创建TestProxy类,实现动态代理

package springaop04_javaDynamicProxy;
//jdk的动态代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestProxy {
    
    public static void main(String[] args) {
        UserDAO target=new UserDAO();
        //根据target得到类对象
        Object proxyObject=getProxy(target);
        //得到代理对象的类对象
        Class clazz = proxyObject.getClass();
        //通过类对象得到类型
        System.out.println(clazz.getName());//这个类是我们写的吗?com.sun.proxy.$Proxy0
        //通过类对象得到类的方法
        Method[] methods=clazz.getDeclaredMethods();
        for (Method method : methods) {
            //select(){调用invocationHandler.invoke(调用invocationHandler.invoke())}
            System.out.println(" "+method.getName());
        }
        //类型转换
        IDAO userIdao=(IDAO) proxyObject;
        //java运行时生成类$Proxy0.select(){调用invocationHandler.invoke()}
        userIdao.select("admin");
    }
    private static Object getProxy(IDAO target) {

        //得到目标类的所有接口
        Class[] interfaces=target.getClass().getInterfaces();
        //得到类加载器
        ClassLoader classLoader = target.getClass().getClassLoader();
        //创建invocationHandler的对象
        MyHandler myHandler = new MyHandler(target);
        //调用java生成代理对象
        Object proxyObject=Proxy.newProxyInstance
                (classLoader, interfaces, myHandler);
        return proxyObject;
    }
    //1,创建InvocatonHandler的实现类
    static class MyHandler implements InvocationHandler{
        IDAO target;
        //通过构造方法接收目标类对象
        public MyHandler(IDAO target) {
            super();
            this.target = target;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("invoke");
            //执行扩展功能
            long startTime = System.nanoTime();
            //调用目标类
            Object result = method.invoke(target, args);
            
            return null;
        }
        
    }
}

AOP实现

利用aop实现查看业务层方法的执行时间。
image.png
第一步:创建启动类Springaop06AopApplication

package com.tedu.springaop06_aop;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Springaop06AopApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springaop06AopApplication.class, args);
    }

}

第二步:创建接口UserService

package com.tedu.springaop06_aop.service;

public interface UserService {
    public String register(String username);
}

第三步:创建实现类UserServiceImpl实现Userservice

package com.tedu.springaop06_aop.service;

import org.springframework.stereotype.Service;

//业务层实现类
@Service//让spring创建一个对象,对象放在spring的容器中
public class UserServiceImpl implements UserService{

    @Override
    public String register(String username) {

        return username+"注册成功了";
    }

}

第四步:创建切面类TimeAspect,实现无侵入式编程

package com.tedu.springaop06_aop.service;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

//切面类:执行扩展功能,实现无侵入式编码
@Component//组件,与@controller,@service功能一样,框架会自动创建对象
@Aspect//这个类是个切面,在执行业务层方法之前或之后执行切面
public class TimeAspect {
    long startTime;//业务层方法开始时间
    //切面像springmvc中的interceptor
    //.pathPattern(/order,/cart)  
    //设置在运行哪些业务层类哪些方法时执行切面TimeAspect
    //pointcut:切入点,设置TimeAspect执行的时机
    //execution:执行
    //第一个*代表的是类
    //第二个*代表的是类中的所有方法
    //(..)代表的是方法的参数可以是任何类型
    //public * 代表方法的返回类型是任何类型
    //注解中定义属性 value()
    //aop框架   遍历方法找@PointCut注解
    @Pointcut("execution(public * com.tedu.springaop06_aop.service.*.*(..))")
    public void aopPointCut() {
        
    }
    //得起始时间
    @Before("aopPointCut()")//在目标方法register之前执行
    public void getStartTime() {
        startTime=System.nanoTime();
    }
    //得结束时间
    @After("aopPointCut()")//在目标方法register之和执行
    public void getEndTime() {
        long endTime=System.nanoTime();
        System.out.println("业务层方法执行的时间:"+(endTime-startTime));
        //关闭服务器,重启,浏览器发请求
        //console中查看日志
    }
}

第五步:创建UserController,调用业务层代码

package com.tedu.springaop06_aop.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.tedu.springaop06_aop.service.UserService;

@RestController
public class UserController {
    //调用业务层,从spring 容器中得对象
    @Autowired //控制反转ioc
    UserService userService;
    @RequestMapping("/register")
    public String register(String username) {
        //调用业务层
        String result = userService.register(username);
        return result;
    }
}

木安
13 声望6 粉丝

« 上一篇
SSM-Springmvc
下一篇 »
SSM-MyBatis