spring的优势
spring的优势
- 方便解耦,简化开发
- AOP编程的支持
- 声明式事务的支持(通过配置的方式实现事务控制)
- 方便程序的测试
- 方便集成各种优秀框架
- 降低JavaEE API的使用难度
- spring的源码是经典的学习范例
常见的配置方式有三种
- 基于XML的配置、基于注解的配置、基于Java的配置
spring配置读取方式
容器方式有三个
AnnotationConfigApplicationContext:使用注解配置
ClassPathXmlApplicationContext:它可以加载类路径下的配置文件。要求配置文件必须在类路径下,不在的话。加载不了。
FileSystemXmlApplicationContext:可以加载磁盘任意位置的配置文件(需要访问权限)@Configuration //@ComponentScan(basePackages = {"com.wangge"}) public class BeansFactory { //使用@Bean的类就无需再加上@Component( //包括@Repository、@Service、@Controller),由于默认是>singleton,会报错! @Bean("saveDao") @Scope("singleton") public SaveDao getSD(){ return new SaveDaoImpl(); } @Bean("saveService") public SaveService getSS(){ return new SaveServiceImpl(); } public static void main(String[] args) { ApplicationContext ctx = new >AnnotationConfigApplicationContext("com.wangge.configurati>on"); SaveService saveService = >(SaveService)ctx.getBean("saveService"); saveService.save(); } }
ApplicationContext 与BeanFactory的比较
ApplicationContext(单例对象适用,)
它在构建核心容器时,创建对象采取的策略是采用立即加载的方式。也就是说,只要一读取完配置文件马上就创建配置文件中配置的对象。
BeanFactory(这是一个顶层接口,多例模式适用,但是使用的很少)
它在构建核心容器时,创建对象采取的策略是采用延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候才真正的创建对象。
创建Bean的三种方式
- 通过全类名(反射)
- 通过工厂方法(静态工厂方法 & 实例工厂方法)
- FactoryBean(实体类实现该接口,但是还是得在xml中配置它,对象简单的时候用这个有点多此一举,复杂对象适用)
依赖注入的三种方式
- 使用构造函数提供(constructor-arg)
- 使用set方法提供(property)
- 使用注解方法提供
spring的测试类
- 应用程序的入口
main方法- junit单元测试中,没有main方法也能执行,因为junit集成了一个main方法,该方法就会判断当前测试类中哪些方法有@Test注解,junit就让有Test注解的方法执行;
- junit不会管我们是否采用spring框架,在执行测试方法时,junit根本不知道我们是不是使用了spring框架,所以也就不会为我们读取配置文件/配置类创建spring核心容器
- 由以上三点可知
当测试方法执行时,没有Ioc容器,就算写了Autowired注解,也无法实现注入导入依赖
使用junit中的@RunWith注解来将main方法替换成spring给我们提供的。
@ContextConfiguration用以告知spring的测试 配置方式 及其 位置。<dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.1.9.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> </dependency>
@RunWith(SpringRunner.class) @ContextConfiguration(classes = {BeansFactory.class} ) public class MyTest { @Autowired private SaveService saveService; @Test public void xx(){ saveService.save(); } }
说一点持久层事务管理的前戏!普通的CRUD不是没有事务的,只是他们各自都拿的不同的connection,因而拥有各自独立的事务!那么要实现多个CRUD操作在同一事务下,我虚需要ThreadLocal对象将connection与线程绑定,从而使一个线程中只有一个能控制事务的对象。当事务完成后还需要解除绑定。
AOP
有关于AOP的术语:
- Joinpoint (连接点):
被拦截到的点,在spring中,这些点是指方法。(所有方法都是连接点)。- Pointcut (切入点):
需要对哪些连接点拦截和增强,那么这些点就称之为切入点。
切入点一定是连接点,连接点不一定是切入点。- Advice (通知/增强) :
所谓通知是指拦截到Joinpoint之后所要做的事情就是通知。
通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。- Introduction (引介) :
引介是一种特殊的通知在不修改类代码的前提下,Introduction 可以在运行期为类动态地添加些方法或Field.- Target(目标对象) :
代理的目标对象。- Weaving (织入) :
是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入。- Proxy (代理) :
一个类被AOP织入增强后,就产生一个结果代理类。
Aspect (切面) :
是切入点和通知(引介)的结合。
基于注解的AOP配置
导入依赖(这个依赖用于解析切点表达式的)
<dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>RELEASE</version> </dependency>
//@Component @Aspect//声明这是一个配置类 public class Logger { @Pointcut("execution(* com.wangge.service.impl.SaveServiceImpl.save())") public void getPointcut(){} @Before("execution(* *..SaveServiceImpl.*())") public void printBeforeLog(){ System.out.println("前置通知"); } @After("getPointcut()") public void printAfter(){ System.out.println("后置"); } }
切点表达式:权限 返回值 包名 类名 方法名(参数)
配置类中开启注解AOP的支持:@EnableAspectJAutoProxy
配置文件中开启注解AOP的支持:<aop:aspectj-autoproxy></ aop:aspectj-autoproxy>