SSM-Spring

1 spring概述

spring是分層的JavaSE及JavaEE應用於全棧的輕量級開源框架,以 IoC (Inverse Of Control:控制反轉/反轉控制)和 AOP (Aspact Oriented Programming:面向切面編程)爲核心,提供了表現層SpringMVC和持久層Spring JDBC以及業務層事務管理等衆多模塊的企業級應用技術,還能整合開源世界中衆多 著名的第三方框架和類庫,逐漸成爲使用多的JavaEE企業應用開源框架。java

spring框架主要用來處理業務間的邏輯,如帳號註冊時的用戶名判斷等等。程序員

spring框架其中最核心的是:IoC控制反轉、DI依賴注入、SpringAOP面向切面編程、事務控制。web

1.1 spring的架構:

Spring 初的目標就是要整合一切優秀資源,而後對外提供一個統一的服務。 Spring 模塊構建在覈心容器之上,核心容器定義了建立、配置和管理 bean 的方式, 以下圖所示:
image.png
組成 Spring 框架的每一個模塊(或組件)均可以單獨存在,或者與其餘一個或多 個模塊聯合實現。每一個模塊的功能以下:
image.pngspring

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依賴springboot

<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註解,由框架進行對象賦值。mvc

第一步:建立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;
    }
}
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息