乐趣区

关于spring:SSMSpring

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 的形式,如下图所示:

组成 Spring 框架的每个模块(或组件)都能够独自存在,或者与其余一个或多 个模块联结实现。每个模块的性能如下:

2 IoC+DI

IoC 是设计思维,IoC 有三个外围:BeanFactory、反射、DI。BeanFactory 利用反射实现对象的创立,DI 实现对象关系治理。

2.1 IoC 管制反转

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

2.1.1 spring 中的 IoC 的实现

第一步:创立 maven 我的项目 spring

第二步:在 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 的底层实现


第一步:创立注解自定义 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 是对动静代理的封装。

切面类 = 切入点(ponitcut())+ 告诉办法 (@Around+@Before+@AfterReturning+@AfterThrowing)

动态代理


第一步:创立接口 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 实现查看业务层办法的执行工夫。

第一步:创立启动类 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;
    }
}
退出移动版