Spring学习
1.IoC容器的实现方法:
-
BeanFactory实现(已经弃用)
-
ApplicationContext实现
ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
2.实现IOC是通过依赖注入来实现的,依赖注入有
-
构造方法注入
//构造方法形式的 public TestDIServiceImpl(TestDao testDao) { this.testDao = testDao; }
xml文件中配置 <constructor-arg index="0" ref="testDao"></constructor-arg> |
-
setter方法注入
//setter方法形式的 public void setTestDao(TestDao testDao) { this.testDao = testDao; } xml文件中配置 <property name="testDao" ref="testDao"></property> |
3.Spring框架采用java的反射机制进行依赖注入
Bean的实例化
构造方法实例化:
public class BeanClass { public String message; public BeanClass() { message = "构造方法实例化Bean"; } public BeanClass(String message) { super(); this.message = message; } } |
静态工厂实例化:
public class BeanStaticFactory { private static BeanClass beanInstance = new BeanClass("调用静态工厂方法实例化Bean"); //需要建立一个工厂方法 静态方法实例化对象 public static BeanClass createInstance() { return beanInstance; } } |
实例工厂实例化:
public class BeanInstanceFactory { public BeanClass createBeanClassInstace() { return new BeanClass("调用工厂实例方法实例化Bean"); } } |
xml配置文件:
<!-- 构造方法实例化Bean --> <bean id="beanConstructorInstance" class="instance.BeanClass"></bean> <!-- 静态工厂实例化 --> <bean id="staticFactoryInstance" class="instance.BeanStaticFactory" factory-method="createInstance"></bean> <!-- 实例工厂实例化 --> <bean id="myFactory" class="instance.BeanInstanceFactory"></bean> <bean id="instanceFactoryInstance" factory-bean="myFactory" factory-method="createBeanClassInstace"></bean> |
Bean实例化的方法
-
构造方法实例化
-
静态工厂实例化
-
实例工厂实例化
基于注解和装配方式的基本用法
注解方式主要是利用context方式在xml文件中配置注解扫描,然后在编写的部分功能代码上使用相应的注解标签对相应层的Bean完成注解
<!-- 注解扫描包下的文件 --> <context:component-scan base-package="annotation"></context:component-scan> |
主要标签:
-
@Repository&@Component
-
功能相同,该注解用于数据访问层(DAO),注解数据访问层的Bean
-
-
@Service
-
用于标注一个业务逻辑组件类(Service)层,功能和@Component相同
-
-
@Controller
-
用于标注一个控制器组件类(SpringMVC的Controller),功能和@Component相同
-
-
@Autowired
-
对类成员、方法及构造方法进行标注,完成自动装配的工作。一般是用于获取某个对象,来调用方法时用到。通过使用此注解标签来消除setter和getter方法。默认按照Bean类型装配
-
-
@Resource
-
功能同上
-
-
@Autowired与@Resource的区别
-
区别在与Resource是按照名称来装配注入的,只有当找不到匹配的名称的时候才采用类型装配。
-
Bean有两种作用域Singleton,还有prototype,默认Singleton
默认注解装配id都是首字母小写
AOP
AOP是面向切面编程,是对OOP的一种补充,是在不改变原有程序的基础上横向修改程序,扩展程序的功能,使得程序满足我们的需求。
采取横向抽取机制,即将分散在各个方法中的重复代码提取出来,然后在程序编译或运行阶段将这些抽取出来的代码应用到需要执行的地方。
AOP允许我们将通用的流程和代码抽取出来,单独实现,然后给出约定的流程,从而把后续开发者的代码织入约定的流程,从而减少大量重复的工作,使得开发者的工作更为简单,这样业务逻辑就更清晰,代码工作量就更少,尤其是我们核心内容——数据库事务更是如此。
AOP的术语
-
切面
-
Aspect:封装横切到系统功能的类
-
-
连接点
-
Joinpoint:程序运行中的一些时间点 before afterReturning等(例如方法的调用与异常的抛出)
-
-
切入点
-
Pointcut:指代需要处理的连接点
-
-
通知
-
Advice:由切面添加到特定的连接点的一段代码,即在定义好的切入点处所要执行的程序代码,可以将其理解为切面开启后切面的的方法,通知是切面的具体体现
-
-
引入
-
Introduction:允许现有的实现类中添加自定义的方法和属性
-
-
目标对象
-
Target Object:指代所有被通知的对象。如果AOP框架使用运行时代理的方式来实现切面,那么通知对象总是一个代理对象
-
-
代理
-
proxy:通知应用到目标对象之后被动态创建的对象
-
-
织入
-
Weaving:将代码插入到目标对象上,从而生成代理对象的过程。Spring AOP通常采用动态代理织入。AspectJ采用编译器织入和类装载期织入
-
AOP动态代理技术:
JDK动态代理,默认的
Cglib动态代理技术
AspectJ框架的AOP开发方式:
-
基于代理类实现
-
基于XML实现
-
基于注解实现
基于代理类实现XML的配置 <!-- 定义目标对象 --> <bean id="testDao" class="dynamic.jdk.TestDaoImpl"></bean> <!-- 定义一个切面 --> <bean id="myAspect" class="spring.proxyfactorybean.MyAspect"></bean> <!-- 使用spring代理工厂定义一个代理对象 --> <bean id="testDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 指定代理实现的接口 --> <property name="proxyInterfaces" value="dynamic.jdk.TestDao"></property> <!-- 指定目标对象 --> <property name="target" ref="testDao"></property> <!-- 指定切面,织入环绕通知 --> <property name="interceptorNames" value="myAspect"></property> <!-- 指定代理方式,true指定Cglib代理,默认为false,JDK代理 --> <property name="proxyTargetClass" value="true"></property> </bean> |
基于XML实现(注解方式类似于这个) <!-- 定义目标对象 --> <bean id="testDao" class="dynamic.jdk.TestDaoImpl"></bean> <!-- 定义切面 --> <bean id="myAspect" class="aspectj.xml.MyAspect"></bean> <!-- AOP配置 --> <aop:config > <!-- 配置切面 --> <aop:aspect ref="myAspect"> <!-- 配置切入点,通知增强哪些方法 因为方法都在这个包下 --> <aop:pointcut expression="execution(* dynamic.jdk.*.*(..))" id="myPointCut"/> <!-- 将通知与切入点关联 --> <!-- 关联前置通知 --> <aop:before method="before" pointcut-ref="myPointCut"/> <aop:after-returning method="afterReturning" pointcut-ref="myPointCut"/> <!-- 关联环绕通知 --> <aop:around method="around" pointcut-ref="myPointCut"/> <!-- 异常 --> <aop:after-throwing method="except" pointcut-ref="myPointCut" throwing="e"/> <!-- 关联后置通知 --> <aop:after method="after" pointcut-ref="myPointCut"/> </aop:aspect> </aop:config> |
为什么要使用AOP
使用AOP便于在原有的代码基础上加入需要实现的新功能,前提是不改动原有的代码,配置AOP切面即可。AOP采取横向抽取机制,即将分散在各个方法中的重复代码提取出来,然后在程序编译或运行阶段将这些抽取出来的代码应用到需要执行的地方。
在业务代码中通常有日志记录、性能统计、安全控制、事务管理、异常操作等。利用OOP很复杂,利用AOP很简单。
为什么要使用声明式事务
为了保证事务的正常运行下去,不出差错,结合AOP的声明式事务管理可以做到在方法的前后进行拦截,然后在方法的前后加入或者创建一个事务,然后根据执行情况进行提交或者回滚,不需要编写额外的代码。
Spring事务管理
编程式事务
在代码中显式的调用beginTransaction、commit、rollback等与事务处理相关的方法,就是编程式事务
有两种编程式事务:
-
基于底层API的编程式事务管理
-
基于TransactionTemplate的编程式事务管理
声明式事务管理(非常重要)
Spring的声明式事务管理是通过AOP技术实现的事务管理,其本质是对方法的前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
声明式事务管理最大的优点就是不用通过编程的方式管理事务,因而不需要在业务逻辑代码中参杂事务处理的代码,只需相关的事务规则说明便可以将事务规则应用到业务逻辑中。通常情况下,在开发中使用声明式事务不仅是因为其简单,更主要是因为这样使得纯业务代码不被污染,极大地方便了后期的代码维护。
与编程式事务管理相比,声明式事务管理唯一的不足就是最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。可以使用变通的方法解决,例如可以将需要进行事务处理的代码块独立为方法等。
实现有两种方式:
-
XML
-
@Transactional注解方式
AOP和声明式事务的结合
<!-- 指定要扫描的包,使得注解生效 --> <context:component-scan base-package="com.statement"></context:component-scan> <!-- 配置数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <!-- mysql数据库驱动 --> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property> <!-- 连接数据库的url --> <property name="url" value="jdbc:mysql://127.0.0.1:3306/springtest?serverTimezone=UTC"></property> <!-- 连接数据库的用户名 --> <property name="username" value="root"></property> <!-- 连接数据库的密码 --> <property name="password" value="cao236476"></property> </bean> <!-- 配置JDBC的模板 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean>
<!-- 为数据源添加事务管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean>
<!-- 编写通知事务声明 --> <tx:advice id="myAdvice" transaction-manager="txManager"> <tx:attributes> <!-- 表示任意方法 --> <tx:method name="*"/> </tx:attributes> </tx:advice> <!-- 编写AOP,让Spring对象自动生成对目标对象的代理,需要使用AspectJ的表达式 --> <aop:config> <aop:pointcut expression="execution(* com.statement.*.*(..))" id="myPointCut"/> <!-- 切面,将切入点与通知相关联 --> <aop:advisor advice-ref="myAdvice" pointcut-ref="myPointCut"/> </aop:config> |
Spring整体就是上面的内容,后面SpringMVC还会拓展学习