很多基础理论知识,如果长时间不看的话,那么很容易就会忘掉,今天就来回顾一下Spring的基础知识吧
Spring的体系结构在Spring中,核心功能被有组织的分配到约二十多个模块中,这些模块分布在测试(Test)、核心容器(Core Container)、面向切面编程(AOP)、植入(Instrumentation)、消息传输(Messaging)、数据的访问/集成(Data Access/Integration)、Web集成等核心模块中。
核心容器(Core Container)Spring的核心容器是其他模块建立的基础,主要包括Spring-beans、Spring-core、Spring-Context、Spring-context-support、Spring-expression等模块。
Spring-core模块是框架的基本组成部分,提供了“控制反转”和“依赖注入”等功能。Spring-beans模块主要是用来提供一个对象工厂BeanFactory,用来创建管理对象bean。Spring-context 通常称为Spring的上下文。为什么叫“上下文”呢?“context”英文译为“语境”,其实将其理解为“环境”,这样应该更容易理解,Spring中的一些程序在执行中需要一个特定的环境,Spring-context就是用来提供这样的环境。Spring-context-support 支持整合第三方库到Spring应用程序的上下文中,也可以将其看做是Spring-context的补充。Spring-expression 提供了强大的表达式语言,是对EL表达式的拓展 AOP和Instrumentation
AOP和Instrumentation的相关模块主要为Spring-aop,Spring-aspects和Spring-instrument
Spring-aop 主要提供了一个面向切面编程的实现方式。Spring-aspects 用来集成AspectJ框架,AspectJ是一个强大的AOP框架。Spring-instrument 支持类的植入和类加载器的实现 消息(Messaging)
Spring4.0以后,提供了对消息传递体系结构和协议的支持
数据访问/集成Spring-jdbc模块,提供了一个JDBC的抽象层,消除了繁琐的JDBC编码。Spring-tx 事务模块 支持对声明式事务的管理Spring-orm 提供对对象关系映射框架的支持,例如Hibernate和JPA。Spring-oxml 提供了对XML和对象映射的支持。Spring-jms 提供对jms的支持,jms指java消息传递服务。
第一个Spring程序
我们最初学习Spring是如何学习的?
1、使用Eclipse创建一个web项目,导入Spring的相关jar包
2、在src目录下创建一个dao包,并在dao下创建一个TestDao接口,在接口中定义一个sayHello()方法
public interface TestDao {
public void sayHello();
}
3、 创建一个TestDao 的实现类TestDaoImpl
public class TestDaoImpl implements TestDao {
@Override
public void sayHello() {
System.out.println("Hi good friend");
}
}
4、在src目录下创建Spring的配置文件,配置文件的名称可以自定义,但习惯上通常起名为applicationContext.xml,在该文件中配置一个TestDaoImpl的Bean,id为 “test”
5、创建一个测试类
public class Test {
@SuppressWarnings("resource")
public static void main(String[] args) {
//初始化Spring容器 加载配置文件
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//通过容器获取TestImpl实例
TestDao testDao = (TestDao) applicationContext.getBean("test");
testDao.sayHello();
}
}
执行main方法后,控制台输出“Hi good friend”,在测试方法中并没有使用new来创建TestDaoImpl对象,而是通过Spring容器获取实现类对象,这就是Spring的IOC机制。
Spring IOC SpringIOC基本概念
当某个Java对象需要调用另一个Java对象,在没有spring的时候,通常会采用new一个需要的对象,但这种方式会增加调用者与被调用者之间的耦合性,不利于代码的升级与维护。但是Spring框架出现后,对象的实例不在由调用者来创建,而是由spring容器来创建,创建对象的权利从调用者转移到了Spring容器上,控制权发生了反转,这就是Spring的控制反转。
Spring常用注解在spring中,可以通过xml配置文件的方式来注入bean,但是如果应用中存在大量的bean,会导致xml文件过于庞大,因此,在实际应用中,更多的会采用注解的方式来实现bean的注入,下面列举一些最基本的注解。
下面看示例代码
1、修改TestDaoImpl实现类如下
@Repository("testDao")
public class TestDaoImpl implements TestDao {
@Override
public void sayHello() {
System.out.println("Hi good friend");
}
}
2、创建service层代码,创建TestService接口和TestServiceImpl实现类,并将实现类TestServiceImpl使用@Service注解标注为业务逻辑层
TestService代码如下
public interface TestService {
public void sayHello();
}
TestServiceImpl代码如下
@Service("testService")
public class TestServiceImpl implements TestService {
@Resource(name = "testDao")
private TestDao testDao;
@Override
public void sayHello() {
testDao.sayHello();
}
}
3、创建Controller层
@Controller
public class TestController {
@Autowired
private TestService testService;
public void sayHello(){
testService.sayHello();
}
}
4、创建配置类ConfigAnnotation
@Configuration
@ComponentScan("*")
public class ConfigAnnotation {
}
5、创建测试类
public class TestAnnotation {
@SuppressWarnings("resource")
public static void main(String[] args) {
//通过配置类 初始化Spring容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigAnnotation.class);
//通过容器获取TestController实例
TestController testController = (TestController) context.getBean(TestController.class);
testController.sayHello();
}
}
Java配置Spring
Spring从4.X开始,开始推荐使用java配置的方式,通过@Configuration和@Bean实现,@Configuration声明在类上,表明当前类是一个配置类,@Bean声明在方法上,声明当前方法的返回值是一个Bean
下面来看一个简单的例子
1、创建一个dao
public class TestDao {
public void say(){
System.out.println("你好 Spring");
}
}
2、创建Service
//注意 这里也没有使用@Service注解
public class TestService {
TestDao testDao;
public void setTestDao(TestDao testDao) {
this.testDao = testDao;
}
public void say(){
testDao.say();
}
}
3、创建Controller
//注意 这里也没有使用@Controller注解
public class TestController {
TestService testService;
public void setTestService(TestService testService) {
this.testService = testService;
}
public void say(){
testService.say();
}
}
4、创建一个配置类
@Configuration
public class Config {
@Bean
public TestDao getTestDao() {
return new TestDao();
}
@Bean
public TestService getTestService() {
TestService ts = new TestService();
//使用set方法注入dao
ts.setTestDao(getTestDao());
return ts;
}
@Bean
public TestController getTestController(){
TestController tc = new TestController();
//使用set方法注入service
tc.setTestService(getTestService());
return tc;
}
}
5、创建测试类
public class TestConfig {
@SuppressWarnings("resource")
public static void main(String[] args) {
//初始化Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
TestController testController = applicationContext.getBean(TestController.class);
testController.say();
}
}
Spring AOP Aop基本概念
如果想在不修改现有程序代码的情况下,实现例如“日志记录”、“安全控制”、“事务处理”等操作,这个时候就需要用到AOP的思想,简单说,就是将重复的代码从各个方法中抽离出来,然后在程序运行的时候,在将抽取出来的代码应用到需要执行的地方。
AOP的术语切面(Aspect):指封装横切到系统中的类。被@Aspect注解声明的类。连接点(Joinpoint): 指程序运行中的一些时间点,如方法的调用或者异常的抛出。切入点(Pointcut) :是指那些需要处理的连接点,通过配置表达式确定那些连接点需要处理,切面、连接点和切入点的关系如图
通知 :在定义好的切入点处所要执行的代码,是切面的具体实现,通知又可以分为六种类型
- 环绕通知:在方法的执行前和执行后,可用于日志记录、事务处理等功能前置通知 在方法的执行前,可用于权限管理等功能后置返回通知 在目标方法执行成功后执行,可用于关闭流,删除临时文件等功能后置最终通知 与返回通知不同的是,不管是否发生异常都会执行异常通知 在方法抛出异常的时候执行,可用于处理异常、记录日志等功能引入通知 在目标类中添加一些新的属性和方法
引入:允许在现有的实现类中添加自定义的方法和属性。目标对象:是指所有被通知的对象,也就是业务逻辑类,比如Controller类。代理:是通知应用到目标对象后,被动态创建的对象。织入:指将切面代码插入到目标对象上,从而生成代理对象的过程。 代码示例
在开始代码之前,先了解一下AOP的一些常用注解
1、创建一个DAO
public interface TestDao {
public void save();
public void update();
public void delete();
}
@Repository
public class TestDaoImpl implements TestDao {
@Override
public void save() {
int i = 1/0;
System.out.println("执行保存方法");
}
@Override
public void update() {
System.out.println("执行修改方法");
}
@Override
public void delete() {
System.out.println("执行删除方法");
}
}
2、创建一个切面类
@Aspect //声明这是一个切面类
@Component //让此切面成为Spring管理的bean
public class MyAspect {
//定义切入点,配置表达式,通知增强哪些方法
//execution(* aop.dao.*.*(..)) 是定义切入点表达式
//参数中第一个 * 表示返回值类型,*表示所有类型
//aop.dao表示的是需要匹配的包名
//第二个*表示的是类名 * 表示匹配所有的类
//第三个* 表示的是方法名,*表示所有方法
//(..)代表方法中的参数 ..表示任意参数
//注意 第一个* 与包名之间要有一个空格
@Pointcut("execution(* aop.dao.*.*(..))")
private void myPointCut(){
}
//前置通知
@Before("myPointCut()")
public void before(JoinPoint jp){
System.out.println("前置通知。。。。。。。");
}
//后置通知
@AfterReturning("myPointCut()")
public void afterReturning(JoinPoint jp){
System.out.println("后置返回通知。。。。。。");
}
//环绕通知
@Around("myPointCut()")
public Object around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知。。。。。。");
Object object = pjp.proceed();
return object;
}
//异常通知
@AfterThrowing(value="myPointCut()",throwing = "e")
public void except(Throwable e){
System.out.println("异常通知"+ e.getMessage());
}
//后置最终通知
@After("myPointCut()")
public void after(){
System.out.println("后置最终通知.........");
}
}
3、创建一个spring的配置类
@Configuration //声明一个配置类
@ComponentScan("aop")//开启自动扫描使用注解的包
@EnableAspectJAutoProxy //开启Spring 对 AspectJ的支持
public class AspectAOPConfig {
}
4、创建测试类
public class AopTest {
@SuppressWarnings("resource")
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AspectAOPConfig.class);
TestDao testDao = context.getBean(TestDao.class);
testDao.save();
System.out.println("=======================================");
testDao.update();
System.out.println("=======================================");
testDao.delete();
context.close();
}
}
查看输入结果



