本文最后更新于 2023-07-23,文章内容可能已经过时,请注意内容的辨别。

Spring核心

框架简介

框架是一个半成品,已经对基础的代码进行了封装并提供相应的API,开发者在使用框架是直接调用封装好的api可以省去很多代码编写,从而提高工作效率和开发速度

企业级系统特点

大规模:用户数量多、数据规模大、功能众多 性能和安全要求高 业务复杂 灵活应变

Spring

简介

轻量级框架, Java EE的春天,当前主流框架

目标

使现有技术更加易用,推进编码最佳实践

内容

  • IoC容器
  • AOP实现
  • 数据访问支持
  • 简化JDBC/ORM 框架
  • 声明式事务
  • Web集成

设计理念

Spring是面向Bean的编程

核心技术

  • 控制反转(IoC:Inversion of Control ) /依赖 注入(DI:Dependency Injection )
  • 面向切面编程(AOP:Aspect Oriented Programming)

优点

  • 低侵入式设计
  • 独立于各种应用服务器
  • 依赖注入特性将组件关系透明化,降低了耦合度
  • 面向切面编程特性允许将通用任务进行集中式处理
  • 与第三方框架的良好整合

组件

组件也是抽象的概念,可以理解为一些符合某种规范的类组合在一起就构成了组件。他可以提供某些特定的功能。J2EE来说,有什么servlet,jsp, javabean,ejb都是组件。但实际他们都是类,只不过有他们特殊的规定。组件和类的关系:符合某种规范的类的组合构成组件

控制反转 / 依赖注入

目的

解耦合。实现每个组件时只关注组件内部的事情

核心思想

将组件对象的控制权从代码本身转移到外部容器 组件化的思想:分离关注点,使用接口,不再关注实现 依赖的注入:将组件的构建和使用分开

什么是控制反转

有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;

实现原理
工厂模式
public class Person {
	public int id;
}
public class Student extends Person {
	public int num;
}
public class Person {
	public int id;
}
public class Factory {
	private final static  String STUDENT="student";
	private final static  String TEACHER="teacher";
	public Person getPerson(String str) {
		if(str.equals(STUDENT)) {
			return new Student();
		}else if(str.equals(TEACHER)) {
			return new Teacher();
		}else {
			return null;
		}
	}
}

class Test1 {
	@Test
	void test() {
		Factory factory = new Factory();
		Student student =(Student) factory.getPerson("student");
		System.out.println(student.toString());
	}
}


与工场模式的区别

不需要new我们的工厂类。由容器去做

什么是依赖注入

动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。

实现原理
反射

举例

这是设值注入要求必须的有set方法才行

public class HelloSpring {
    private String who;
   public  void  print(){

       System.out.println(who+"打印了");

   }

    public void setWho(String who) {
        this.who = who;
    }
}
import javafx.application.Application;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloSpringTest {

  @Test
    public  void demo(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    HelloSpring helloSpring = (HelloSpring)context.getBean("helloSpring");
    helloSpring.print();
  }

}

<?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">
    <bean id="helloSpring" class="demo.HelloSpring">
        <property name="who">
            <value>Spring</value>
        </property>
    </bean>

</beans>

AOP(面向切面)

目标

专心做事

原理

将复杂的需求分解出不同方面,将散布在系统中的公共功能集中解决 采用代理机制组装起来运行,在不改变原程序的基础上对代码段进行增强处理,增加新的功能

相关术语

  • 增强处理(Advice)

  • 切入点(Pointcut)

  • 连接点(Join Point)

    jp.getTarget()连接方法所在的目标类
    jp.getArgs()连接点方法的信息
    jp.getSignature()连接点方法参数数组
    
  • 切面(Aspect)

  • 目标对象(Target object)

  • AOP代理(AOP proxy)

  • 织入(Weaving)

使用AOP步骤

1.定义目标方法

2.定义增强方法

3.写配置文件

增强处理

前置增强

后置增强

public interface IUserservice {

    public void addUser();

}
public class UserServices implements IUserservice{


    @Override
    public void addUser() {
        System.out.println("加了一个用户");
    }
}
public class LoggerUntil {
   //private static Logger log = Logger.getLogger(LoggerUntil.class);
    public void before(JoinPoint jp){
        System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
        //log.info(""+jp.getTarget()+jp.getSignature()+ Arrays.toString(jp.getArgs()));
    }
    public void afterReturning(JoinPoint jp,Object result){
        System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
                + " 方法。方法返回值:" + result);
        //log.info(""+jp.getTarget()+jp.getSignature()+result);
    }
}
public class HelloSpringTest {

  @Test
    public  void demo(){
    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    IUserservice service = (IUserservice) ctx.getBean("userService");
    User user = new User();
    user.setId(1);
    user.setUsername("test");
    user.setPassword("123456");
    user.setEmail("test@xxx.com");
    service.addUser();
  }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
    <bean id="helloSpring" class="demo.HelloSpring">
        <property name="who">
            <value>Spring</value>
        </property>
    </bean>
    <bean id="userService" class="service.UserServices" />
    <bean id="loggerUntil" class="aop.LoggerUntil"/>
    <aop:config>
        <aop:pointcut id="pointcut"  expression="execution(  public void addUser())"/>
        <aop:aspect ref="loggerUntil">
            <aop:before method="before" pointcut-ref="pointcut"/>
            <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
        </aop:aspect>
    </aop:config>
   <!-- <aop:aspectj-autoproxy proxy-target-class="true"/>-->
</beans>

环绕增强

异常抛出增强

最终增强