Spring

                                             Spring

1 什么是Spring

产生于2003年,是一个分层的Javase/ee一站式轻量级开源框架。从功能的角度来定义的,从本质意义上来讲,Spring是一个Java库,它提供了一个软件框架,这个框架目的是使软件之间的逻辑更加清晰,配置更灵活。

2 Spring的优点

2.1 简化开发,方便解耦(IOC)

Spring本身是一个工厂(容器),创建管理对象以及维护对象之间关系。

方便解耦:体现了高内聚,低耦合。内聚:每个模块尽可能独立完成自己的功能,不依赖于模块外部的代码。模块设计推荐采用高内聚。耦合:模块与模块之间接口的复杂程度,模块之间联系越复杂耦合度越高,牵一发而动全身。如:一个用户 用户类user里面的方法全部是用户相关的,比如用户登录方法,调用了获取用户基本信息方法, 这些方法内部相互依赖,相互调用,依赖程度很高,但是却没有定义订单 支付的方法,这就是高内聚。用户的支付模块,订单模块,不直接关联,用另外一个或者多个service去调用,支付和订单不直接调用,从而解耦合,订单业务修改了,支付调用的地方不用修改,因为是另外一个类的的作为中间人去调用的,这就是低耦合。

2.2 支持AOP编程

面向切面编程,拦截进行添加增强。简单理解就是在运行时,动态的将代码切入到类的指定方法的指定位置上,这种思想就是面向切面的编程思想。

2.3 支持优秀框架集成

不排斥各种优秀框架,如mybatis,springmvc,hiberbate,quartz,struts2等等一系列的优秀框架的直接支持。

2.4 简化Javaee的API

 spring框架是对javaee良好补充,如对JDBC、JavaMail等,提供了封装,使这些API应用起来非常简单。

2.5 支持事务声明

只需要通过配置就可以完成对事物的管理,不需要手动编程。

2.6 支持junit集成

可以通过注解方便的测试Spring程序。

 

3 Spring Framework核心

3.1 IOC(控制反转)

IOC 全称为 Inversion Of Control,也叫做DI(Dependency Injection)依赖注入。

IOC的定义:就是由 Spring IOC 容器来负责对象的生命周期和对象之间的关系。

一般我们需要某个对象是采用new的方式直接创建,这个过程复杂而又繁琐,我们又必须面对每个环节,还需要销毁它,并且该对象和它依赖的对象耦合在一起。其实我们依赖一个对象并不是依赖他本身而是依赖他提供的服务,我们需要它的时候它能提供服务,至于是我们自己手动创建的还是别人给我们的并不重要。当我们需要的时候别人给我们,管理都交给了别人,相当于别人为自己服务,给我们的人就是IOC容器。

IOC为被注入对象提供被依赖对象也有如下几种方式:构造方法注入、setter方法注入、接口注入。

构造器注入:被注入的对象通过在其构造方法中声明依赖对象的参数列表,让外部知道它需要哪些依赖对象。

setter 方法注入:当前对象只需要为其所依赖的对象提供相对应的 setter 方法,就可以通过该方法将相应的依赖对象设置到被注入对象中。

接口方式注入:它需要被依赖的对象实现不必要的接口,带有侵入性。一般都不推荐这种方式。

3.2 Spring IoC的五个核心体系

(1)Resource体系和ResourceLoader体系:Resource体系是对资源的抽象,每个实现类都代表一种资源的访问策略,如ClasspathResource 、 InputStreamResource、URLResource ,FileSystemResource 等。ResourceLoader体系进行统一资源加载,实现类如:ClassRelativeResourceLoader、FileSystemResourceLoader,PathMatchingResourcePatternResolver。

(2)BeanFactory体系:是 IOC 必备的数据结构,BeanDefinition 是她的基本结构,它内部维护着一个 BeanDefinition map ,并可根据 BeanDefinition 的描述进行 bean 的创建和管理。BeanFacoty 有三个直接子类 ListableBeanFactory、HierarchicalBeanFactory 和 AutowireCapableBeanFactory,DefaultListableBeanFactory 是最终默认实现,实现了所有接口。

(3)BeanDefinition体系:用来描述 Spring 中的 Bean 对象

(4)BeanDefinitionReader体系:读取 Spring 的配置文件的内容,并将其转换成 IOC 容器内部的数据结构:BeanDefinition。

(5)ApplicationContext系统:这个就是Spring容器,继承 BeanFactory,继承 MessageSource,提供国际化的标准访问策略;继承 ApplicationEventPublisher ,提供强大的事件机制;扩展 ResourceLoader,可以用来加载多个 Resource,可以灵活访问不同的资源。

3.3 AOP(面向切面)

什么是AOP:采用横向抽取方式,在运行期间将增强代码添加到目标对象方法的一种思想,底层采用动态代理。

常见AOP框架:Spring aop,aspectj,jboss aop

AOP常见应用场景:事务管理(声明式事务),日志系统,性能监测

切面:可以这么理解编程中,对象与对象之间,方法与方法之间,模块与模块之间都是一个个切面。

AOP相关专业术语如下:

target(目标对象)需要添加增强代码的对象
joinpoint(连接点)可以添加增强代码的目标方法
pointcut(切入点)一组集中的joinpoint,定义了相应的 Advice 将要发生的地方
advice(通知)实现特定接口的增强代码
aspect(切面)增强代码和切入点之间形成的逻辑面
weaver(织入)增强代码添加到切入点过程

注意:Spring只支持方法类型的joinpoint

advice的类型:

before在joinpoint前被执行的advice
after-returning在joinpoint正常返回后执行的advice
after-throwing当joinpoint抛出异常后执行的advice
after(final)无论一个joinpoint是正常退出还是发生了异常都会执行的advice
around在joinpoint前和joinpoint退出后都会执行的advice
introduction可以为原有的对象添加属性和方法

3.4 代理

什么是代理:为其他对象提供一种代理以控制对这个对象的访问,可以实现访问目标之前或之后实现预处理和后续处理。

(1)静态代理:接口编写代理类。

特点:代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多.同时,一旦接口增加方法,目标对象与代理对象都要维护。

(2)动态代理(JDK代理,接口代理):接口 + 委托类

特点:代理对象,不需要实现接口;代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型

package dao.imple;
import dao.UserDao;
public class UserDaoImple implements UserDao {
	@Override
	public void add(String str) {
		System.out.println("添加" + str);
	}
	@Override
	public int remove(int i) {
		System.out.println("删除");		
		return i-1;
	}

}
package test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import dao.UserDao;
import dao.imple.UserDaoImple;
public class AOPTest {
	public static void main(String[] args) {	
		//1. 创建委托类对象
		UserDao userDao = new UserDaoImple();
		//2. 给委托类对象创建代理对象(实现同一个接口)		
		UserDao proxy = (UserDao)Proxy.newProxyInstance(
				//ClassLoader loader:类加载器        
				userDao.getClass().getClassLoader(), 
				//Class<?>[] interfaces:委托类对象实现的接口们
				userDao.getClass().getInterfaces(),
				//InvocationHandler h:拦截方法的处理
				new InvocationHandler() {	
					//Object proxy:代理对象        Method method方法的描述对象   Object[] args方法参数
					//执行代理类对象的方法
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						System.out.println("方法前执行");
						//手动调用委托类的方法
						Object obj = method.invoke(userDao, args);
						System.out.println("方法后执行");
						return obj;
					}
				});
		//3. 访问代理对象的方法(实际上是访问委托类的方法)
		proxy.add("添加");
		proxy.remove(2);
	}
}

(3)Cglib动态代理:代理对象继承委托类(知晓委托类的方法)

Cglib代理,也叫作子类代理,在内存中构建一个子类对象从而实现对目标对象功能的扩展。静态代理和动态代理目标对象都需要实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理。

需要使用字节码增强jar包(asm.jar/cglib.jar),spring的核心包pring-core包括了cglib功能。

注意:代理的类不能为final,否则报错;目标对象的方法如果为final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法

package dao.imple;

public class UserDaoImple2{
	public void add() {
		System.out.println("添加" );
	}
	public void remove() {
		System.out.println("删除");
	}

}
package test;
import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import dao.imple.UserDaoImple2;
public class AOPTest {
	public static void main(String[] args) {
		//1. 创建委托类对象
		UserDaoImple2 userDaoImple2 = new UserDaoImple2();
		//2. 给委托类创建代理对象(代理类对象继承委托类)
		Enhancer enhancer = new Enhancer();
		//设置父类
		enhancer.setSuperclass(UserDaoImple2.class);
		//方法拦截处理
		enhancer.setCallback(new MethodInterceptor() {
			@Override
			public Object intercept(Object proxy, Method method, Object[] arg2, MethodProxy methodProxy ) throws Throwable {
				System.out.println("方法前执行");
				Object obj = method.invoke(userDaoImple2, arg2);
				System.out.println("方法后前执行");
				return obj;
			}
		});
		UserDaoImple2 proxy = (UserDaoImple2)enhancer.create();
		//3. 访问代理对象的方法(实际上是访问委托类的方法)
		proxy.add();
		proxy.remove();
	}
}

在Spring的AOP编程中:如果加入容器的目标对象有实现接口,用JDK代理。如果目标对象没有实现接口,用Cglib代理

 

3.5 IOC及AOP实例

需要的基本jar包:

spring-aop: spring aop框架          spring-aspects:aspectj框架(规范)         aspectjweaver:aspectj框架中织入的实现

aopalliance:aop联盟(制定通知规范)          commons-logging日志

 

委托类

package service.imple;

import dao.UserDao;
import service.UserService;

/**
 * @Description 委托类
 * @author refuel
 * @version v1.0
 */
public class UserServiceImple implements UserService {
	UserDao dao;	
	public UserServiceImple(UserDao dao) {
		this.dao=dao;	
	}
	@Override
	public void add(String str) {
		dao.add(str);
	}
	@Override
	public int remove(int i) {
		
		return dao.remove(i);
	}	
}



package service;
public interface UserService {
	void add(String str);
	int remove(int i);
}



package dao.imple;
import dao.UserDao;
public class UserDaoImple implements UserDao {
	@Override
	public void add(String str) {
		System.out.println("添加" + str);
	}
	@Override
	public int remove(int i) {
		System.out.println("删除");		
		return i-1;
	}
}


package dao;
public interface UserDao {
	void add(String str);
	int remove(int i);
}

增强代码类

package advice;
/**
 * @Description 委托类
 * @author refuel
 * @version v1.0
 */
public class Myaspect {
	public void begin() {
		System.out.println("开始");
	}
	public void end() {
		System.out.println("结束");
	}
}

applicationContext.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!-- schema约束 -->
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop"
    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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
      
	<bean id="userdao" class="dao.imple.UserDaoImple"></bean>
	<!-- 目标类对象 -->
	<bean id="userservice" class="service.imple.UserServiceImple">
		<constructor-arg name="dao" ref="userdao"></constructor-arg>
	</bean>
	<!-- 增强类对象 -->
	<bean id="myaspect" class="advice.Myaspect"></bean>
	<!-- 织入增强代码 -->
	<aop:config >
		<!-- 切入点:寻找增强代码
		id:唯一标识
		expression: 设定作为切入点方法
		execution(返回值 包名.类名.方法名(参数列表))   * 通配
              execution(* service.impl.UserServiceImpl.*(..))
              execution(* service..*(..))
		 -->
		<aop:pointcut expression="execution(* service.imple.UserServiceImple.*(..))" id="userPintCut"/>
		<!-- 切面:切入点加增强代码
		aop:怎样添加增强代码到切入点
		ref:增强代码对象
		 -->
		<aop:aspect ref="myaspect">
			<aop:after method="begin" pointcut-ref="userPintCut"/>
			<aop:after-returning method="end" pointcut-ref="userPintCut"/>
			<aop:declare-parents types-matching="" implement-interface=""/>
		</aop:aspect>
	</aop:config>
</beans>

测试类

package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import service.UserService;
public class AOPTest {
	public static void main(String[] args) {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService bean = ac.getBean("userservice", UserService.class);
		bean.add("a");
		System.out.println(bean.remove(5));
	}
}	

 

上述配置文件的注入方式为手动注入,可以配置自动注入如下

   <bean id="userservice" class="service.impl.UserServiceImpl" autowire=""></bean> 
   no: 默认,不自动注入
   byType: 按照类型注入,从整个ioc容器中寻找属性同类型的值实现注入,
			如果找不到,就不注入;如果找到一个,则注入成功; 如果找到多个,则抛出异常。
   byName: 按照名称注入,从整个ioc容器中寻找属性同名的值实现注入,
           如果找不到,就不注入;
           如果找到一个,则注入成功。
   constructor: 自动注入中的构造注入(等同于设值注入中的byType)

3.6 注解实现装配

常见注解:

<bean class=""></bean>  ---> @Component  (组件) 默认id就是类名

<bean id="" class=""></bean>  --> @Component("id")

@Controller: 表示层          @Service: 业务逻辑层              @Repository: 数据持久层

applicationContext.xml配置文件

 注解注入类型:

@Autowired: 按照类型注入

@Qualifier("id"):按照名称注入

@Resources(name="id"):按照名称注入

 

applicationContext.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    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
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
        
  <!-- 扫描配置了注解的对象,将它注册为spring的bean放置在ioc容器中 -->
   <context:component-scan base-package="cn.refuel.service,cn.refuel.advice"></context:component-scan>
   
   <!-- 切面配置的注解生效 -->
   <aop:aspectj-autoproxy/>
</beans>

增强代码类

package advice;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
public class CustomAspect {
	//环绕(手动调用方法)  
    @Around("pointCut()")
	public Object around(ProceedingJoinPoint joinPoint) {
		Object proceed = null;
		try {
			System.out.println("前置增强");
			//执行方法(放行目标方法)
			proceed = joinPoint.proceed();
			System.out.println("后置增强");
		} catch (Throwable e) {
			System.out.println("异常增强");
		}finally {
			System.out.println("最终增强");
		}
		return proceed;
	}	
	//配置切入点
	@Pointcut("execution(* service..*(..))")
	public void pointCut() {}	
	@Before("pointCut()")
	public void before(JoinPoint joinPoint) {
		Object target = joinPoint.getTarget();
		System.out.println("target:"+target);
		String name = joinPoint.getSignature().getName();
		System.out.println("name"+name);
		System.out.println("前置增强");
	}
	
	@AfterReturning("pointCut()")
	public void afterReturning() {
		System.out.println("后置增强");
	}
	
	@AfterThrowing("pointCut()")
	public void afterThrowing() {
		System.out.println("异常增强");
	}
	
	@After("pointCut()")
	public void after() {
		System.out.println("最终增强");
	}

}

委托类

package cn.refuel.service.imple;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import cn.refuel.dao.UserInfoDao;
import cn.refuel.service.UserInfoService;
//目标类
@Service("userinfoservice")
public class UserInfoServiceImple implements UserInfoService {
	
	@Autowired
	/* @Qualifier("userinfodao") */
	UserInfoDao userInfoDao;
	public UserInfoServiceImple(UserInfoDao userInfoDao) {
		this.userInfoDao=userInfoDao;
	}
	@Override
	public void addUser() {
		System.out.println("add");
	}

	@Override
	public void deleteUser() {
		System.out.println("remove");
	}

}



package cn.refuel.service;
public interface UserInfoService {	
	void addUser();
	void deleteUser();
	
}



package cn.refuel.dao.imple;
import org.springframework.stereotype.Repository;
import cn.refuel.dao.UserInfoDao;
@Repository("userinfodao")
public class UserInfoDaoImple implements UserInfoDao {

	@Override
	public void addUser() {
		System.out.println("添加");
	}

	@Override
	public void deleteUser() {
		System.out.println("删除");
	}

}


package cn.refuel.dao;

public interface UserInfoDao {
	void addUser();
	void deleteUser();
}


测试类

package cn.refuel.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.refuel.service.UserInfoService;
public class MainTest {
	public static void main(String[] args) {
		//加载配置文件,获取IOC容器
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserInfoService bean = ac.getBean("userservice", UserInfoService.class);
		bean.addUser();
	}
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值