Spring基础-Core和AOP

什么是Spring

  • spring是一个轻量级的“一站式”的开源框架。spring框架涵盖了javaEE开发的所有的技术思想和设计原理。这些技术思想和原理并不是Spring创新的技术,只是把已经存在的技术思想重新整合成的一个新的框架。
  • JavaEE官方平台的核心框架:EJB(Enterprise JavaBean)。重量级开发JavaEE应用的框架,相当于Spring+Hibernate技术组合,但是EJB可以做分布式开发。EJB应用只能部署在重量级的容器(服务器),例如,JBoss,
    Weblogic , WebSphere, Spring应用可以部署在web容器中,例如:Tomcat.

Spring框架组成

在这里插入图片描述

  • 核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC)
    模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。

  • Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
    Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring
    的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。

  • Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring
    DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。

  • Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。

  • Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web
    模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。

  • Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

  • JDBC Template:对jdbc的高度封装。

Spring Core 核心模块

先了解两个重要的概念:

  • IOC(Inverse Of Controll)控制反转
    传统的java实例的创建是由程序通过new关键字创建的,称为“硬编码”。控制反转指的是这种传统的创建对象的方式的“反转”,也就是由spring对象容器来创建。简单而言,就是容器托管对象。
  • DI (Dependency Injection)依赖注入
    依赖,指的是对象与对象的某种关系。依赖关系的初始化不通过“硬编码”完成,而是“容器“进行初始化,也就是由容器注入该实例的引用。

伪代码:

class Human{
    
    
    private Head head;
    private Body body;
    private Leg  leg;
    ....
    public void doSomething(Work work){
    
    
        work.cal();
    }
}
class Head{
    
    }
class Body{
    
    }
class Leg{
    
    }
interface Work {
    
    }
class  UserService{
    
    
    private UserDao userDao;
}

依赖注入的方式:

  • setter注入 通过属性的setter方法完成初始化
  • 构造器注入 通过构造函数
  • 接口注入 例如:servlet的doGet()和doPost()方法 ,一般在框架或容器中使用较多
  • 注解注入 整合时使用最方便(最常用)

spring基础的入门程序

  • setter注入
	<bean id="person" class="com.gec.spring.bean.Person">
		<property name="name" value="李四"></property>
		<property name="speaking" value="Good Afternoon"></property>
	</bean>
  • 构造器注入
	<bean id="host" class="com.gec.spring.bean.Host"></bean>
	<bean id="display" class="com.gec.spring.bean.Display"></bean>
	
	<bean id="computer" class="com.gec.spring.bean.Computer">
		<constructor-arg index="0" ref="host"></constructor-arg>
		<constructor-arg index="1" ref="display"></constructor-arg>
	</bean>
  • P命名空间注入
	<bean id="host" class="com.gec.spring.bean.Host"></bean>
	<bean id="display" class="com.gec.spring.bean.Display"></bean>
	<bean id="computer" class="com.gec.spring.bean.Computer" p:host-ref="host" p:display-ref="display"/>
  • 特殊数据的注入,指的是集合的注入
	<bean id="department" class="com.gec.spring.bean.Department">
		<property name="name" value="财务部"></property>
		<!-- List的注入 -->
		<property name="empList">
			<list>
				<ref bean="emp1"/>
				<ref bean="emp2"/>
			</list>
		</property>
		
		<!-- Set的注入 -->
		<property name="empSet">
			<set>
				<ref bean="emp1"/>
				<ref bean="emp2"/>
			</set>
		</property>
		
		<!-- Map类型的注入 -->
		<property name="empMap">
			<map>
				<entry key="1" value-ref="emp1"></entry>
				<entry key="2" value-ref="emp2"></entry>
			</map>
		</property>
		
		<property name="pp">
			<props>
				<prop key="pp1">emp1</prop>
				<prop key="pp2">emp2</prop>
			</props>
		</property>
	</bean>
	
	<bean id="emp1" class="com.gec.spring.bean.Employee" p:name="张三" p:id="1"></bean>
	<bean id="emp2" class="com.gec.spring.bean.Employee" p:name="李四" p:id="2"></bean>
  • 自动装配
    在这里插入图片描述

spring管理Bean的作用域:

  1. 单例 singleton (默认)
<bean id="date1" class="java.util.Date" scope="singleton"></bean>
  1. 原型(多例) prototype

以下三种在javaweb应用中使用

  1. request
  2. session
  3. Global Session

Spring 的 AOP编程

  1. AOP Aspect Oriented Programming 面向切面编程, “拦截器”。
  2. 在JavaEE技术体系中,拦截技术相当重要。主要的作用是降低组件间的“耦合度”。
    javaweb 过滤器 过滤一切可访问的资源(拦截http请求的),包括,jsp,servlet,css,js,…
    struts2 springmvc 包含系统的拦截器和自定义拦截器 拦截控制器
    spring AOP编程 拦截业务层的方法。
  3. AOP编程和OOP编程的共同点:都是解决应用的共性问题,如果在应用中找不到继承关系,可以使用AOP来解决通用性问题。 spring
    aop 中拦截的方式(方法的增强), 粒度很细:
public void dosomething(){
    
    
    
    try{
    
    
       //1.前置增强
       //3. 环绕增强(前置) 
       service();  //核心的业务 
       //3. 环绕增强(后置)
       //2. 后置增强
    }catch(){
    
    
       //4.异常增强 
    }finally{
    
    
       //5. 最终增强 
    }
    
}

  1. AOP的术语:
    – aspect 切面 相当于拦截器类,解决通用性问题
    – pointcut 切入点 哪些类的哪些方法要被拦截
    – weaver 织入 对被拦截的目标对象的进一步封装
  2. AOP编程的实现方式
    – 实现接口的方式 , 在低版本的spring中常用 ,每种增强都会对应有一个接口。
    – schema的方式, 直接使用xml文档配置各种增强方式
    (1)切面类
package com.gec.spring.aop;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

/**
 * aspect : 切面类  ,解决通用性问题
 * @author gec
 *
 */
public class MyAOP {
    
    

	//前置增强
	public void before(JoinPoint joinPoint) {
    
    
		Object[] args = joinPoint.getArgs();  //获取拦截方法的参数列表
		String methodName = joinPoint.getSignature().getName(); //补拦截方法的名称 
		Object target = joinPoint.getTarget(); //被拦截的目标实例(业务类的实例)
		
		System.out.println("前置  方法名:" + methodName+",参数列表:"+Arrays.toString(args)+",目标对象:"+target);
	}
	
	//后置增强: 带返回值参数
	public void afterReturning(JoinPoint joinPoint,Object returnValue) {
    
    
		Object[] args = joinPoint.getArgs();  //获取拦截方法的参数列表
		String methodName = joinPoint.getSignature().getName(); //补拦截方法的名称 
		Object target = joinPoint.getTarget(); //被拦截的目标实例(业务类的实例)
		
		System.out.println("后置  方法名:" + methodName+",参数列表:"+Arrays.toString(args)+",目标对象:"+target+",返回值:"+returnValue);
	}
	
	//环绕增强
	public Object arround(ProceedingJoinPoint pjp) throws Throwable{
    
    
		Object[] args = pjp.getArgs();  //获取拦截方法的参数列表
		String methodName = pjp.getSignature().getName(); //补拦截方法的名称 
		Object target = pjp.getTarget(); //被拦截的目标实例(业务类的实例)
		System.out.println("环绕(前置)方法名:" + methodName+",参数列表:"+Arrays.toString(args)+",目标对象:"+target);
		
		//核心业务方法的调用
		Object returnValue = pjp.proceed();
		
		System.out.println("环绕(后置)  方法名:" + methodName+",参数列表:"+Arrays.toString(args)+",目标对象:"+target+",返回值:"+returnValue);
		
		return returnValue;	
	}
}

(2)schema配置

<?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:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	http://www.springframework.org/schema/aop 
	http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">

	<bean id="userService" class="com.gec.spring.service.impl.UserServiceImpl"></bean>
	<bean id="myAop" class="com.gec.spring.aop.MyAOP"></bean>
	
	<!-- aop的织入weaver -->
	<aop:config>
		<aop:pointcut id="pointcut" expression="execution(public * com.gec.spring.service.impl.*.*(..))"/>
		<aop:aspect ref="myAop">
			<aop:before method="before" pointcut-ref="pointcut"/>
			<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="returnValue"/>
			<aop:around method="arround" pointcut-ref="pointcut"/>
		</aop:aspect>
	</aop:config>
</beans>

– 注解的方式, 使用注解说明增强方式
(1) 切面类

package com.gec.spring.aop;

import java.util.Arrays;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyInterceptor {
    
    
	
	//1. 前置增强
	@Before("execution(public * com.gec.spring.service.impl.*.*(..))")
	public void before(JoinPoint joinPoint) {
    
    
		Object[] args = joinPoint.getArgs(); //被拦截方法的参数列表
		String methodName = joinPoint.getSignature().getName(); // 被拦截方法名
		Object obj = joinPoint.getTarget(); //被拦截的目标对象,被代理对象
		
		System.out.println("前置 方法名:" + methodName + ", 参数列表:" + Arrays.toString(args)+",拦截的目标对象:"+obj);
	}
	
	//2. 后置通知
	@AfterReturning(pointcut="execution(public * com.gec.spring.service.impl.*.*(..))",returning="returnValue")
	public void afterReturning(JoinPoint joinPoint,Object returnValue) {
    
    
		Object[] args = joinPoint.getArgs(); //被拦截方法的参数列表
		String methodName = joinPoint.getSignature().getName(); // 被拦截方法名
		Object obj = joinPoint.getTarget(); //被拦截的目标对象,被代理对象
		
		System.out.println("后置 方法名:" + methodName + ", 参数列表:" + Arrays.toString(args)+",拦截的目标对象:"+obj + ",返回值:"+returnValue);

	}
	
	//环绕增强
	@Around("execution(public * com.gec.spring.service.impl.*.*(..))")
	public Object arround(ProceedingJoinPoint pjp) throws Throwable {
    
    
		Object[] args = pjp.getArgs(); //被拦截方法的参数列表
		String methodName = pjp.getSignature().getName(); // 被拦截方法名
		Object obj = pjp.getTarget(); //被拦截的目标对象,被代理对象
		
		System.out.println("环绕-前置 方法名:" + methodName + ", 参数列表:" + Arrays.toString(args)+",拦截的目标对象:"+obj);
		
		//业务方法的调用
		Object returnValue = pjp.proceed();
		
		System.out.println("环绕-后置  返回值 :" + returnValue);
		
		return returnValue;
		
	}
}

(2) spring的核心xml文件中启动注解

	 <bean id="myInterceptor" class="com.gec.spring.aop.MyInterceptor"></bean>
	 <!-- 启动aop注解配置 -->
	 <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

Aop编程的应用

AOP的设计模式- 代理设计模式

代理模式:对代理目标的功能增强,也就是“拦截”。

1.静态代理
组成 :

  • 抽象主题
  • 真实主题
  • 代理类

2.动态代理
动态代理类的实现

package com.gec.spring.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理类
 * 
 * @author gec
 * 
 */
public class DynaProxyBean implements InvocationHandler {
    
    
	// 代理的目标对象,业务类的实例 
	private Object proxyObj;

	private DynaProxyBean(Object proxyObj) {
    
    
		this.proxyObj = proxyObj;
	}

	/**
	 * 产生代理对象的工厂方法
	 * 
	 * @param obj
	 *            被代理目标对象
	 * @return
	 */
	public static Object proxy(Object obj) {
    
    
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
				.getClass().getInterfaces(), new DynaProxyBean(obj));

	}

	@Override  //增强   Method表示被代理目标对象的核心方法
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
    
    
		preRequest();
		Object returnValue = method.invoke(this.proxyObj, args);
		return returnValue;
	}
	
	private void preRequest() {
    
    
		System.out.println("前置增强");
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_45879810/article/details/108455122