答:spring是一个轻量级的J2EE框架,它可以让java的企业级开发变的非常简单
答:1.2,2.0,2.5,3.0,3.1,4.0,4.2,5.x
我们学习阶段:刚开始使用:4.2,使用maven以后版本改为4.37,在微服务架构中我们使用 5.1.6
准备工作:
在idea中,配置applicationContext.xml文件的模板
它是一种思想,它是指创建对象、管理对象的方式,以前是自己创建自己管理,现在变成由spring容器创建,容器进行管理
它是IOC的具体实现,有了spring以后,类中属性的初始化,依赖于spring容器注入的参数,才可以完成初始化,这一个
过程就称为:“依赖注入”
在没有spring之间,假设:一个层次要调用另一个层次的方法(例如:Service调用Dao层的方法),可以在一个类,
自己创建另一个类的实例
public class InfService {
private InfDao dao;
public void setDao(InfDao dao) {
this.dao = dao;
}
public void addData(){
dao.add();
}
}
@@@@@@@:这种new对象的写法,属于一种高耦合的写法
在spring应用中,不提倡,调用者自己创建被调用者的实例,在spring的应用中,所有对象都是由spring容器来创建,
哪里,需要这个对象, spring容器就会把对象传递到哪里
步骤:
1、创建一个java工程
2、导入jar
spring 4.2.4
core,beans,context,expression
sprign 3.0.2
logging (spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1)
3、生成spring的主配置文件 applicationContext.xml
4、创建InfDao
package org.java.dao;
public class InfDao {
public void add(){
System.out.println("向mysql添加了数据");
}
}
5、在applicationContext.xml文件中,注册InfDao
6、创建InfService
public class InfService {
private InfDao dao;
public void setDao(InfDao dao) {
this.dao = dao;
}
public void addData(){
dao.add();
}
}
7、在applicationContext.xml文件中,配置InfService,并且配置要给当前对象注入的对象
8、编写测试类进行测试
package org.java.demo;
import org.java.service.InfService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo {
public static void main(String[] args) {
ApplicationContext cxf = new ClassPathXmlApplicationContext("applicationContext.xml");
InfService service = (InfService) cxf.getBean("infService");
service.addData();
}
}
ApplicationContext:它是spring容器,它负责产生对象,只有在applicationContext.xml文件中,注册过的对象,它才能产生
答:目的,将组件的创建与使用强制分开,降低组件与组件之间的耦合度
我们要使用某一个组件,只需要声明即可,不需要关心该组件如合创建,在运行时,spring容器会把创建好的组件
自动注入到需要它的地方
注意:一般Service,Dao这两层都要写接口
接口的写法:
书上的规范:
开发中的写法:
1、对象的注入 ref
2、值的注入 value
3、集合的注入 (List,Map,Set)
@@@list:
AAA
BBB
CCC
@@@@Set
111
222
333
@@@@ Map
one.....
two.....
1、依赖注入
@@@:这种方式是通过属性的set方法进行注入
private InfDao dao;
public void setDao(InfDao dao) {
this.dao = dao;
}
2、构造注入
@@@:这种方式是通过构造方法进行注入
需要在类中,编写一个带参数的构造方法
public InfService(InfDao dao,String msg, int score) {
this.dao = dao;
}
3、自动绑定注入
@@@@@:这种方式注入,属性依然要生成set方法
这种写法,需要什么类型,自己在spring容器去找对应的类型,然后自己注入
在spring应用中,为了简化开发过程,简化xml文件中的代码,spring提供了一种注解的方式
使用spring注解(spring注释)的好处:
采用spring注解的方式配置程序:
1、创建java工程
2、导入jar
spring 4.2
core,beans,context,expression
增加: aop,aspects
spring 3.0.2
logging
增加: aop联盟 aopalliance,
3.0.2.RELEASE-dependencies\org.aopalliance\com.springsource.org.aopalliance\1.0.0
织入的包 weaver
3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
3、编写applicationContext.xml
4、在xml文件启用spring注解
spring中的注解符号:
由于
所以,只要采用组件扫描,
@Autowired
private InfDao dao;-----------此代码,表示,按类型自动注入byType
@@@@@@@@如果采用这一种方式,注入,要求,匹配的类型,只能有一个
@Autowired
@Qualifier("dao2")
private InfDao dao; ----------此代码,表示,按照名称,自动注入 byName
在使用spring注解时,如果没有给当前组件指定别名,系统将生成,默认的别名:
生成的原则如下: 类名,首字母小写
注意:一旦给组件指定别名,默认别名就失效
答:AOP称为“面向切面编程”,也称为“面向方面编程”
答:aop用于集中处理程序中涉及到公共性的一些辅助功能,让程序员集中精力编写业务逻辑
答:aop主要是通过一种“通知”的形式来实现。
通知的类型有四种:它们会在不同的时候,自动的调用
答:要配置通知,我们要通过一种"代理模式"的方式进行配置
答:通过代理模式,可以在实现原有功能的基础上,附加额外功能
将程序中,涉及到的一些辅助性的一些公共问题,集中编写成一个公共的模块,通过一定的配置,当需要这些功能的时候,
系统将会自动进行调用
AOP实现方式,主要是通过一种"通知"的方式进行实现 (Advice)
spring的AOP提供了四种类型的通知,分别在不同的时候自动运行:
@@@@@@@@@如何配置通知
在AOP中,配置通知,需要使用一种设计模式:代理模式(proxy)
代理模式:通过代理可以在实现原有功能的基础上,附加额外功能
@@@@@@@:使用代理模式的目的,要在原有功能的基础上,附加额外功能
applicationContext.xml
org.java.service.BuyBookService
before
after
AfterAdvice.java
package org.java.advice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("");
System.out.println("------后置通知----------");
}
}
BeforeAdvice.java
package org.java.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* 前置通知,此处的代码,在执行业务逻辑代码之前,自动运行
*/
public class BeforeAdvice implements MethodBeforeAdvice {
/**
*
* @param method:即将执行的是类中的哪一个业务方法
* @param objects:调用方法时,要传递给方法的参数有哪些
* @param o:即将要执行的是哪一个业务逻辑类
* @throws Throwable
*/
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("-------进入前置通知类-------------");
System.out.println("即将访问的业务类是:"+o.getClass());
System.out.println("即将访问的业务方法是:"+method.getName());
System.out.println("即将传递给方法的参数有:"+ Arrays.toString(objects));
System.out.println("-------离开前置通知类-------------");
System.out.println("");
}
}
BuyBookServiceImpl.java
package org.java.service.impl;
import org.java.service.BuyBookService;
/**
* 业务实现类
*/
public class BuyBookServiceImpl implements BuyBookService {
@Override
public String buyBook(String who, String bookName) {
System.out.println("-----------------进入业务逻辑类------------------");
System.out.println("正在进行业务逻辑处理");
System.out.println("-----------------离开业务逻辑类------------------");
return who+",购买了书:"+bookName;
}
}
测试
package org.java.demo;
import org.java.service.BuyBookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Demo {
public static void main(String[] args) {
ApplicationContext cxf = new ClassPathXmlApplicationContext("applicationContext.xml");
BuyBookService service = (BuyBookService) cxf.getBean("proxy");
service.buyBook("张三","环球地理");
}
}
前置通知:它会在业务逻辑类调用之前先执行,前置通知需要实现接口: MethodBeforeAdvice
后置通知:它会在业务逻辑类调用之后执行,后置通知,需要实现接口:AfterReturningAdvice
异常通知:它会在业务逻辑类执行过程中,如果产生了异常才会被调用,异常通知,需要实现接口ThrowsAdvice
异常通知中,没有强制实现的方法,但我们写的方法要满足以下规则:
public void afterThrowing(Method method,Object[] args,Object target,Exception ex ){
}
环绕通知:它把整个业务逻辑类的执行包含在通知里面,环绕通知,一般实现:MethodInterceptor
采用自动代理
优点:
before
after
mythrows
buyBookService
service2
service3
声明式代理
优点:
@Before(value = "execution(* org.java.service.*.*(..))")
public void before(JoinPoint jp){
System.out.println("------------------------进入前置通知");
}