一、Spring框架介绍
Spring框架是为了解决企业应用开发复杂性而创建的,是Java应用钟最广的框架,它的成功来源于设计思想,而不是技术本身,即IOC(inversion of control,控制反转) 和AOP(Aspect oriented programming,面向切面编程) 的核心概念。它将面向接口的编程思想贯穿整个系统,解决了项目中各层的松耦合问题,简化企业项目的开发。
1、IOC(控制反转)
Spring IOC像是一个容器,认为Java资源都是Java Bean,IOC的目标是管理好Bean。在 Spring IOC里管理了各种 Bean(资源),它们的创建、事件、行为、资源之间的依赖关系等,都由 Spring IOC 容器根据配置文件的描述来完成管理任务。因此,使用 Spring 框架就是将对象的创建、销毁、初始化等一系列生命周期的过程,都交给 Spring 容器来处理。
如果没有IOC?
平常我们写代码,如果一个类ServiceA要调用另一个类ServiceB的某个方法,就需要在类ServiceA的方法里new一个类ServiceB的对象。
假如现在你有几十个类都需要用到ServiceB的某个方法,那你就需要在几十个类里,都分别去new一个ServiceB的对象。
有一天,业务改了,你写了一个新的类ServiceC,类ServiceB就废弃不用了。那之前调用ServiceB的几十个类,你就得把几十个类中
“ServiceB b= new ServiceB ()”的代码改成“ServiceC c= new ServiceC ()”
如果你漏掉了一处,那项目跑的时候又去调用对象ServiceB 的方法,但此时ServiceB 的逻辑已经废弃了…
IOC解决了什么问题?
创建一个接口ServiceB,然后给它创建一个实现类ServiceBImpl。在ServiceA里注入接口ServiceB。
这个时候,当你的项目启动的时候,Spring 容器在底层使用java的反射技术,去扫描项目中的Bean。它首先发现类 ServiceA 里引用了接口ServiceB,然后它去找现在是谁实现了接口ServiceB,它发现原来是类ServiceBImpl实现了接口ServiceB,此时根据这层依赖关系,它就会在类 ServiceA实例化一个ServiceBImpl的对象。依赖注入,就是Spring容器用反射技术,根据注解或配置文件去创建Bean, 然后根据Bean之间的依赖和引入关系,去实例化对应的对象,实现了类和类之间彻底的解耦。
2、AOP(面向切面的编程)
AOP解决了什么问题?
解决重复代码问题。AOP,就是通过动态代理技术生成类的一个动态代理类,这个动态代理类实现了你的类的所有方法,然后根据你的注解,给每个方法织入一些增强代码。从而避免了项目中大量重复代码,一改就得改几十个方法的问题了。
二、简单项目(完整代码)
蛋糕店项目:可以进行制作多种口味(柠檬和芝士)蛋糕操作,输入需要制作的蛋糕口味后,使用AOP模拟实现了在制作开始前检查烤箱是否适合烘培、烘培结束后打包蛋糕、送出蛋糕的功能,制作完成后会输出到控制台。
Cake.java
package cn.java.bean;
public class Cake {
String type ="";
public void addMilk(){
}
public void addFlour(){
}
public String getName(){
return type;
}
}
CheeseCake.java
package cn.java.bean;
public class CheeseCake extends Cake{
@Override
public void addMilk() {
System.out.println("给蛋糕加牛奶!");
}
@Override
public void addFlour() {
System.out.println("给蛋糕加面粉!");
}
@Override
public String getName() {
return "芝士蛋糕";
}
}
LemonCake.java
package cn.java.bean;
public class LemonCake extends Cake{
@Override
public void addMilk() {
System.out.println("给蛋糕加牛奶!");
}
@Override
public void addFlour() {
System.out.println("给蛋糕加面粉!");
}
@Override
public String getName() {
return "柠檬蛋糕";
}
}
CakeDao.java
package cn.java.dao;
import cn.java.bean.Cake;
public interface CakeDao {
public int addCake(Cake cake);
}
CakeDaoImpl.java
package cn.java.dao.impl;
import cn.java.bean.Cake;
import cn.java.dao.CakeDao;
public class CakeDaoImpl implements CakeDao {
@Override
public int addCake(Cake cake) {
System.out.println("cake" +"对象信息为:"+cake);
System.out.println("已将cake订单存入账本");
return 1;
}
}
CakeMakeService.java
package cn.java.service;
import org.springframework.stereotype.Service;
@Service
public interface CakeMakeService {
public void CakeMake(String type);
public void CakeMakeAndPack(String type);
}
CakeMakeServiceImpl.java
package cn.java.service.impl;
import cn.java.bean.Cake;
import cn.java.dao.CakeDao;
import cn.java.service.CakeMakeService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;
import java.applet.AppletContext;
import java.util.HashMap;
@Service
public class CakeMakeServiceImpl implements CakeMakeService {
@Override
public void CakeMake(String type) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
Cake cake = (Cake) context.getBean(type);
cake.addMilk();
cake.addFlour();
String result = cake.getName();
System.out.println("叮叮叮叮~ "+result+"新鲜出炉!");
}
@Override
public void CakeMakeAndPack(String type) {
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
Cake cake = (Cake) context.getBean(type);
CakeDao cakeDaoImpl = (CakeDao) context.getBean("CakeDaoImpl");
cake.addMilk();
cake.addFlour();
String result = cake.getName();
System.out.println("叮叮叮叮~ "+result+"新鲜出炉!");
cakeDaoImpl.addCake(cake);
}
}
CheckBefore.java
package cn.java.aop;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class CheckBefore {
public void checkSafe(){
System.out.println("[AOP前置通知]: 正在检查当前烤箱是否可以开始烘培......");
}
public void checkSuc(){
System.out.println("[AOP前置通知]: 当前机器正常!开始烘培....");
}
}
DeliveryAfter.java
package cn.java.aop;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class DeliveryAfter {
public void deliveryExit(){
System.out.println("[AOP结束通知]: 已安全送出蛋糕.....");
}
}
PackAfter.java
package cn.java.aop;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class PackAfter {
public void pack() {
System.out.println("[AOP返回通知]: 正在打包蛋糕....");
}
}
aop.xml
<!-- 配置目标类,运算bean -->
<bean id="cakeServiceImpl" class="cn.java.service.impl.CakeMakeServiceImpl" >
</bean>
<!-- AOP实验-->
<!-- 配置切面类,检查bean ,第一个切面-->
<bean id="CheckBefore" class="cn.java.aop.CheckBefore"></bean>
<!-- 配置切面类,打包bean ,第二个切面-->
<bean id="PackAfter" class="cn.java.aop.PackAfter"></bean>
<!-- 配置切面类,送出bean ,第三个切面-->
<bean id="DeliveryAfter" class="cn.java.aop.DeliveryAfter"></bean>
<!-- <aop:config></aop:config>-->
<!--2. 配置aop,开始将目标方法和各切面中的通知方法,进行织入-->
<aop:config>
<!-- 配置连接点(切入点)-->
<aop:pointcut expression="execution (* cn.java.service.impl.CakeMakeServiceImpl.* (..))" id="cakePoint"/>
<!-- 配置各切面,不要哪个切面时,注释掉即可 -->
<!-- 配置检测检查环境切面 1. CheckBefore,aop:before:表示前置通知
-->
<aop:aspect ref="CheckBefore" >
<aop:before method="checkSafe" pointcut-ref="cakePoint"/>
<aop:before method="checkSuc" pointcut-ref="cakePoint"/>
</aop:aspect>
<!-- 配置打包切面 2:PackAfter,aop:after:表示后置通知
order="2":表示执行的顺序,数字越大越先执行
-->
<aop:aspect ref="PackAfter" order="2">
<aop:after method="pack" pointcut-ref="cakePoint"/>
</aop:aspect>
<!-- 配置送出切面 3:DeliveryAfter,aop:after:后置通知
order="1":表示执行的顺序,数字越大越先执行
-->
<aop:aspect ref="DeliveryAfter" order="1">
<aop:after method="deliveryExit" pointcut-ref="cakePoint"/>
</aop:aspect>
</aop:config>
application.xml
<bean id="Cake" class="cn.java.bean.Cake">
</bean>
<bean id="Lemon" class="cn.java.bean.LemonCake" parent="Cake">
</bean>
<bean id="Cheese" class="cn.java.bean.CheeseCake" parent="Cake">
</bean>
<bean id="CakeDaoImpl" class="cn.java.dao.impl.CakeDaoImpl">
</bean>
<!-- 引入局部配置文件 -->
<import resource="aop.xml"/>
log4j.properties
# log4JÈÕÖ¾¿ò¼ÜµÄÅäÖÃÎļþ ÎļþÃû×Ö²»ÄܸÄ
# DEBUG ±íʾÈÕÖ¾µÄ¼¶±ð µ÷ÊÔ
# Console ÈÕÖ¾´òÓ¡ÔÚ¿ØÖÆ̨
log4j.rootLogger=INFO, Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
# ÄÄЩÈÕÖ¾ÐèÒª´òÓ¡
log4j.logger.java.sql.ResultSet=INFO
log4j.logger.org.apache=INFO
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
test1.java
import cn.java.dao.CakeDao;
import cn.java.service.CakeMakeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class test1 {
@Test
public void testCalServiceImpl(){
ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
CakeMakeService cakeMakeServiceImp = (CakeMakeService) context.getBean("cakeServiceImpl");
System.out.println("------------------------CakeMake方法测试------------------------");
cakeMakeServiceImp.CakeMake("Lemon");
System.out.println("------------------------------------------------");
cakeMakeServiceImp.CakeMake("Cheese");
System.out.println("------------------------------------------------");
System.out.println("------------------------CakeMakeAndPack方法测试------------------------");
cakeMakeServiceImp.CakeMakeAndPack("Lemon");
System.out.println("------------------------------------------------");
cakeMakeServiceImp.CakeMakeAndPack("Cheese");
System.out.println("------------------------------------------------");
}
}
三、运行结果
test1运行结果