原文链接:Spring学习总结
Spring是一个开源的设计层面框架,它解决的是业务逻辑层和其他层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一栈式) 轻量级开源框架。
Spring的出现取代了EJB的臃肿、低效、繁琐复杂、脱离现实。
IOC其是一种设计思想,将创建对象的权利交给Spring,由IOC统一加载和管理,让Spring去管理对象生命周期,极大的解决了程序耦合性高的问题。
IOC的核心思想在于,资源不由使用资源的双方管理,而由不使用资源的第三方管理,这可以带来很多好处:
举个栗子:
比如甲方需要一双袜子,而乙方它卖一双袜子它要把袜子卖出去,并不需要自己去直接找到一个买家来完成袜子的卖出。它也只需要找第三方,告诉别人我要卖一双袜子。这样甲乙双方进行交易活动,都不需要自己直接去找卖家,相当于程序内部开放接口,卖家由第三方作为参数传入。甲乙互相不依赖,而且只有在进行交易活动的时候,甲才和乙产生联系。反之亦然。
这样做什么好处么呢?甲乙可以在对方不真实存在的情况下独立存在,而且保证不交易时候无联系,想交易的时候可以很容易的产生联系。甲乙交易活动不需要双方见面,避免了双方的互不信任造成交易失败的问题。因为交易由第三方来负责联系,而且甲乙都认为第三方可靠。那么交易就能很可靠很灵活的产生和进行了,这就是IOC的核心思想甲乙双方将不在相互依懒!
Spring IOC容器有两种BeanFactory和ApplicationContext,BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身。ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层的 BeanFactory。
BeanFactory 接口位于类结构树的顶端 ,IOC容器所设定的最基本功能规范。
BeanFactory最主要的方法就是getBean(String beanName),这个方法从容器中返回特别名称的Bean。
BeanFactory的三个子接口:
public interface BeanFactory {
/**
* 获取产生对象的FactoryBean
* 如:myObject是一个FactoryBean,使用&myObject得到的是FactoryBean
*/
String FACTORY_BEAN_PREFIX = "&";
/**
* 获取IoC容器中管理的bean
* @param name
* @return
* @throws BeansException
*/
Object getBean(String name) throws BeansException;
/**
* 判断容器是否含有指定名称的bean
* @param name
* @return
*/
boolean containsBean(String name);
/**
* 检查指定名称的bean是否是单例(可以在BeanDefinition中指定)
* @param name
* @return
* @throws NoSuchBeanDefinitionException
*/
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
/**
* 检查指定名称的bean是否是prototype类型(可以在BeanDefinition中指定)
* @param name
* @return
* @throws NoSuchBeanDefinitionException
*/
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
/**
* 检查指定名称的bean的Class类型是否是特定Class类型
* @param name
* @param targetType 用户指定
* @return
* @throws NoSuchBeanDefinitionException
*/
boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;
/**
* 查询指定名称bean的Class类型
* @param name
* @return
* @throws NoSuchBeanDefinitionException
*/
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
/**
* 查询指定名称bean的所有别名(用户在BeanDefinition中指定的)
* @param name
* @return
*/
String[] getAliases(String name);
}
ApplicationContext app = new ClassPathXmlApplicationContext("配置文件.xml");
类名 对象名 =(类名)app.getBean(" ");
从 ApplicationContext 的继承机构可以看到,ApplicationContext 继承了BeanFactory,也就是说,ApplicationContext拥有BeanFactory的全部功能。ApplicationContext 是通过将容器的功能委派给DefaultListableBeanFactory来实现。除了继承BeanFactory,还有ResourceLoader、EnvironmentCapable、ApplicationEventPublisher、MessageSource等接口,也就说明ApplicationContext 除了容器的功能外,还囊括了资源的处理、环境、事件发布、国际化等。
<?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">
<!-- 若没写id,则默认为com.test.Man#0,#0为一个计数形式 -->
<bean id="man" class="com.test.Man"></bean>
</beans>
public class Test {
public static void main(String[] args) {
//加载项目中的spring配置文件到容器
//ApplicationContext context = new ClassPathXmlApplicationContext("resouces/applicationContext.xml");
//加载系统盘中的配置文件到容器
ApplicationContext context = new FileSystemXmlApplicationContext("E:/Spring/applicationContext.xml");
//从容器中获取对象实例
Man man = context.getBean(Man.class);
man.driveCar();
}
}
IOC重点是如何在系统运行中动态向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。
比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 Spring我们就只需要告诉Spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,Spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由 Spring注入到A中的,依赖注入的名字就这么来的。
那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,Spring就是通过反射来实现注入的。
理解DI的关键是:依赖。为什么需要依赖,谁注入谁,注入了什么。
应用程序依赖于IOC容器,为什么需要依赖:应用程序需要IOC容器来提供对象需要的外部资源比如对数据库操作的对象,IOC容器注入这个,应用程序依赖这个对象
IOC和DI有什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:依赖注入,相对IOC 而言,依赖注入明确描述了被注入对象依赖IOC容器配置依赖对象!
@Component:可以用于注册所有bean
@Repository:主要用于注册dao层的bean
@Controller: 主要用于注册控制层的bean
@Service: 主要用于注册服务层的bean
@Resource:java的注解,默认以byName的方式去匹配与属性名相同的bean的id,如果没有找到就会以byType的方式查找,如果byType查找到多个的话,使用@Qualifier注解(spring注解)指定某个具体名称的bean。
@Autowired:spring注解,默认也是以byName的方式去匹配与属性名相
同的bean的id,如果没有找到,就通过byType的方式去查找,如果查找到多个,用@Qualifier注解限定具体使用哪个。
@Autowired
private IUserDao userDao;
但是如果IUserDao有多个实现类则需要:
@Autowired
@Qualifier("指定具体实现")
private IUserDao userDao;
在软件业,AOP为Aspect Oriented Programming的缩写,意为:[面向切面编程],通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,使函数式编程降低,提高程序的可重用性,同时提高了开发的效率。
@Aspect
public class UserInterceptor {
@Pointcut("execution( * org.srm.practice.service.*.*(..))")
public void user() {
}
@Before("user()")
public void sayHello() {
System.out.println("前置");
}
@After("user()")
public void sayGoodbey() {
System.out.println("后置");
}
@Around("user()")
public void sayAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知..环绕前");
pjp.proceed();//执行方法
System.out.println("环绕通知..环绕后");
}
}
Spring支持编程式事务管理和声明式事务管理两种方式。
编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,Spring推荐使用TransactionTemplate。
声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中
隔离级别是指若干个并发的事务之间的隔离程度。
TransactionDefinition 接口中定义了五个表示隔离级别的常量:
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。
在TransactionDefinition定义中包括了如下几个表示传播行为的常量: