Spring是一个轻量级开源框架,是为了解决企业级编程开发中的复杂性,实现敏捷开发的应用性框架
Spring通过一种称作控制反转(IoC)的技术促进了低耦合。一个对象依赖的其它对象会通过被动的方式传递进来,容器在对象初始化时不等对象发送请求就主动将依赖传递给它,他的底层设计模式采用了工厂模式。
Spring的两大核心控制反转(IoC)和面向切面(AOP)
DI依赖注入
没什么好说的直接上代码,看完之后就能理解的差不多了
Dao层
public interface UserDao {
void getUser();
}
实现Dao
public class UserDaoImpl implements UserDao{
@Override
public void getUser() {
System.out.println("获取用户数据");
}
}
service层
public interface UserService {
void getUser();
}
实现service
public class UserServiceImpl implements UserService{
private UserDao userDao=new UserDaoImpl();
@Override
public void getUser() {
userDao.getUser();
}
}
测试
public class MyTest {
//测试类
public static void main(String[] args) {
UserService service=new UserServiceImpl();
service.getUser();
}
}
输出:
获取用户数据
我们获取了用户的数据,这里我们直接在serviceImpl里直接new出来的,如果我们想获取mysql数据 是不是还需要再实现一个类,然后把private UserDao userDao=new UserDaoImpl();改成private UserDao userDao=new MysqlDaoImpl();这样才可以实现 这样的话就造成了一个耦合太紧的问题,例如,玩家的武器只能是剑,而不能把剑替换成枪,想要替换为枪 就需要修改所以涉及的代码,在小量代码中不是什么问题 在大量代码中就很费力,这时候就要用到依赖注入,通过玩家想要的东西去注入到业务层 从而实现自由切换不需要修改涉及的代码。
第一种实现方式:构造器注入
把之前new的去掉,通过有参构造将我们需要实现的类注入到UserDao中就可以实现,如果我们想要获取mysql数据 就只需要把new UserServiceImpl(new UserDaoImpl());改成new UserServiceImpl(new MysqlDaoImpl());
mysqlDaoImpl同样是实现了Userdao
第二种实现方式:set注入 (重点)
创建一个xml文件 配置信息
这里的<property name="userDao" ref="user"></property>需要注意 name要和上面set方法的参数名一致不然会爆红
而ref就是上面两个bean的id 如果你想要获取用户数据就是user 想要获取mysql数据就 mysql
测试这边第一句话是找到xml配置文件注意要和你命名的xxx.xml文件名一致。第二句话是获取UserServiceImpl,use是你注入UserServiceImpl的bean的id,然后获取方法就OK了
拓展注入方式:自行百度
控制反转(IOC)
IoC:控制反转,不是一种技术而是一种设计思想。
控制:在传统javaSE程序设计,我们直接通过new创建对象,这是程序主动去创建依赖对象;而Ioc有专门一个容器来创建这些对象,由Ioc容器来控制对象的创建,谁控制了谁?当然是Ioc容器控制了对象,控制了什么,主要控制了外部资源获取。
反转:传统应用程序是由我们自己在对象中主动控制去直接获取对象,这是正转;而反转是由容器来帮忙创建注入依赖对象;什么是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
简单粗糙的来讲就是Ioc容器是个盒子 原来你是直接new对象 现在就是把对象扔进盒子spring去new这个对象 new的过程看不见 想用的时候直接拿来用就行了
切面编程(AOP)
面向切面(AOP),它是允许通过分离业务逻辑和事务管理进行内聚性开发,AOP可以拦截指定的方法并且对方法增强,且无需侵入到业务代码中,使业务与非业务逻辑分离。
aop的实现方式
前期准备工作
创建一个service 写几个方法
实现service
然后搞两个日志类
开始配置xml
注意红框是需要的,前三个bean将类放入spring容器管理,使用aop:config配置
aop:pointcut表示切点 从哪里切入,execution是一个表达式
第一个*:表示返回值的类型任意;
com.it.service.UserServiceImpl: AOP所切的服务的包名,即,我们的业务部分
.*(..):表示任何方法名,括号表示参数,两个点表示任何参数类型
aop:advisor表示在切点应用什么类
测试输出:
com.it.service.UserServiceImpl的add方法被执行了
add a user
执行了add方法,返回结果为:null
进程已结束,退出代码0
第二种实现方式,我们只需要写一个类
配置方式 还是一样将这个类注入
aop:aspect:切面声明 ref表示某个类是切面
aop:before:前置增强 方法执行前执行 第一种实现方式我们是通过实现MethodBeforeAdvice类来完成的
aop:after:后置增强 方法执行后执行 第一种实现方式我们是通过实现AfterReturningAdvice类来完成的
测试方法不变
第三种实现方式 是使用注解的方式
新建一个类
@Aspect==aop:aspect; @Before==aop:before ; @After==aop:after
@Around是一个环绕增强 方法参数表示连接点
xml配置
注入类 aop:aspectj-autoproxy表示启动注解
输出:
先执行的环绕前 pj.proceed()方法表示执行方法 执行完环绕后 执行后置增强