一、Spring概述
(一)spring是什么
spring是一个高度灵活的轻量级框架,其目的是降低企业级应用开发的复杂度。
spring在当前的j2ee项目中应用非常广泛,采用java 语言开发。
Spring是免费开源的,地址:
https://spring.io/projects/spring-framework
(二)spring功能介绍
Spring 容器提供了IOC机制,可以创建对象以及管理对象之间的调用关系,避免了硬编码造成的程序耦合。
提供了AOP(面向切面编程方式)功能,可以实现很多特定功能。
声明式事务控制处理。
对jdbc进行了轻量级的封装,可以更加灵活的去操作数据库。
提供了MVC设计模式的解决方案
提供了文件上传、定时器等常用工具类。
对于其他优秀框架的支持(如:Struts、Hibernate、MyBatis、Quartz等)
(三)spring功能模块划分
二、JAVA类的耦合与解耦
(一)什么是程序的耦合
在开发中,可能会写很多的类,而有些类之间不可避免的产生依赖关系,这种依赖关系称之为耦合。
有些依赖关系是必须的,有些依赖关系可以通过优化代码来解除的。
代码示例
public class CustomerServiceImpl implements CustomerService
以上的代码表示:业务层调用持久层,并且此时业务层在依赖持久层的接口和实现类。如果此时没有持久层实现类,编译将不能通过。这种依赖关系就是我们可以通过优化代码解决的。
还有如下面的代码:
我们的类依赖了MySQL的具体驱动类,如果这时候因为某些原因数据库的品牌从MySQL改为Oracle,那么需要通过改源码来修改数据库驱动。这显然不是我们想要的。
public class JdbcDemo01{
public static void main(String[] args) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
}}
(二)解决耦合的思路
当是我们学习JDBC时,是通过反射来注册驱动的,代码如下:
Class.forName("com.mysql.jdbc.Driver");
这时的好处是,我们的类中不再依赖具体的驱动类,此时就算删除mysql的驱动jar包,依然可以编译。但是因为没有驱动类,所以不能运行。
不过,此处也有个问题,就是我们反射类对象的全限定类名字符串是在java类中写死的,一旦要改还是要修改源码。
解决这个问题也很简单,使用配置文件配置。
1.2.1 工厂模式解耦
在实际开发中我们可以把所有的dao和service和action对象使用配置文件配置起来,当启动服务器应用加载的时候,通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。
2.2.2 控制反转-Inversion Of Control
上面解耦的思路有2个问题:
1、存哪去?
分析:由于我们是很多对象,肯定要找个集合来存。这时候有Map和List供选择。
到底选Map还是List就看我们有没有查找需求。有查找需求,选Map。
所以我们的答案就是
在应用加载时,创建一个Map,用于存放action,Service和dao对象。
我们把这个map称之为容器。
2、还是没解释什么是工厂?
工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。
原来:
我们在获取对象时,都是采用new的方式。是主动的。
现在:
我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的。
这种被动接收的方式获取对象的思想就是控制反转,它是spring框架的核心之一。
它的作用只有一个:削减计算机程序的耦合。
三、工厂设计模式
什么是工厂设计模式?
工厂设计模式,顾名思义,就是用来生产对象的,在java中,万物皆对象,这些对象都需要创建,如果创建的时候直接new该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要修改一遍,这显然违背了软件设计的开闭原则,如果我们使用工厂来生产对象,我们就只和工厂打交道就可以了,彻底和对象解耦,如果要更换对象,直接在工厂里更换该对象即可,达到了与对象解耦的目的;所以说,工厂模式最大的优点就是:解耦
定义:一个工厂方法,依据传入的参数,生成对应的产品对象;
角色:
1、抽象产品
2、具体产品
3、具体工厂
4、产品使用者
使用说明:先将产品类抽象出来,比如,苹果和梨都属于水果,抽象出来一个水果类Fruit,苹果和梨就是具体的产品类,然后创建一个水果工厂,分别用来创建苹果和梨;代码如下:
水果接口
public interface Fruit {
void whatIm();
}
具体类 苹果
public class Apple implements Fruit {
@Override
public void whatIm() {
//苹果
}
}
具体类 梨
public class Pear implements Fruit {
@Override
public void whatIm() {
//梨
}
}
具体工厂 水果工厂
public class FruitFactory {
public Fruit createFruit(String type) {
if (type.equals("apple")) {//生产苹果
return new Apple();
} else if (type.equals("pear")) {//生产梨
return new Pear();
}
return null;
}
}
产品使用
FruitFactory mFactory = new FruitFactory();
Apple apple = (Apple) mFactory.createFruit("apple");//获得苹果
Pear pear = (Pear) mFactory.createFruit("pear");//获得梨
package com.tjetc.domain;
public interface Fruit {
void whatIm();
}
package com.tjetc.domain;
public class Apple implements Fruit {
@Override
public void whatIm() {
System.out.println("我是苹果");
}
}
package com.tjetc.domain;
public class Pear implements Fruit {
@Override
public void whatIm() {
System.out.println("我是梨");
}
}
package com.tjetc.domain;
public class FruitFactory {
public Fruit createFruit(String type){
if (type.equals("apple")){
return new Apple();
}
else if (type.equals("pear")){
return new Pear();
}
return null;
}
}
public static void main(String[] args) {
// 创建水果工厂
FruitFactory fruitFactory = new FruitFactory();
// 通过工厂生产水果
Fruit apple = fruitFactory.createFruit("apple");
Fruit pear = fruitFactory.createFruit("pear");
apple.whatIm();
pear.whatIm();
}
四、IoC概述及作用
(一)什么是IoC
Inversion of Control:控制权的转移,创建对象的权利由应用程序转移到容器称为控制反转
(二)IoC的作用
削减计算机程序的耦合(解除我们代码中的依赖关系)
五、Spring基于XML的IoC配置入门
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<bean id="userService" class="com.tjetc.service.UserService"></bean>
package com.tjetc.service;
public class UserService {
public UserService() {
System.out.println(“UserService()”);
}
public void add(){
System.out.println("UserService.add()");
}
}
package com.tjetc;
import com.tjetc.service.UserService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(“applicationContext.xml”);
UserService userService = context.getBean(UserService.class);
userService.add();
}
}
UserService()
UserService.add()
六、Spring基于XML的IoC配置
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.8.RELEASE</version>
</dependency>
<!-- 告诉spring容器创建一个userDao对象-->
<bean id="userDao" class="com.tjetc.dao.UserDao"></bean>
<!-- 告诉spring容器创建一个userService对象-->
<bean id="userService" class="com.tjetc.service.UserService">
<!-- 使用属性的setter方法注入setUserDao-->
<property name="userDao" ref="userDao"></property>
</bean>
package com.tjetc.service;
public class UserService {
public UserService() {
System.out.println("UserService()");
}
public void add(){
System.out.println("UserService.add()");
}
}
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserService() {
System.out.println("UserService()");
}
public void add(){
System.out.println("UserService.add()");
userDao.add();
}
}
package com.tjetc.dao;
public class UserDao {
public void add(){
System.out.println("userDao.add()");
}
}
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean(UserService.class);
userService.add();
}
UserService()
UserService.add()
userDao.add()
七、构造方法注入
public UserService(UserDao userDao) {
System.out.println("UserService.UserService");
this.userDao = userDao;
}
<!-- bean:让spring容器创建对象 id:代表bean(就是new好的java对象)的名字 class:代表你要spring容器创建的类的全限定名-->
<bean id="userService" class="com.tjetc.service.UserService">
<constructor-arg name="userDao" ref="userDao"></constructor-arg>
</bean>
<!-- 配置userDao的bean节点-->
<bean id="userDao" class="com.tjetc.dao.UserDao"></bean>
八、Spring基于Annotation的IoC配置
Annotation:注解
<!--配置组件的扫描com.tjetc本包及其子孙包下的所有的在类上标注有@Controller,@Service,@Repository,@Component注解的类,
spring会把标注了这些注解的类当做你配置bean节点一样纳入spring容器管理-->
<context:component-scan base-package="com.tjetc"></context:component-scan>
package com.tjetc.service;
import com.tjetc.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserService() {
System.out.println("UserService()");
}
public void add(){
System.out.println("UserService.add()");
userDao.add();
}
}
package com.tjetc.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
public void add(){
System.out.println("userDao.add()");
}
}
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean(UserService.class);
userService.add();
}
UserService()
UserService.add()
userDao.add()
【总结】
1.什么是IOC?
Inversion of Control 控制反转 创建对象的权利由应用程序转移到了容器称之为控制反转
2.Ioc作用
削减耦合,减少依赖
3.基于XML的Ioc配置
1.pom.xml: spring-context
2.applicationContext.xml <bean id="bean的名字" class="类的全限定名">
3.测试:
ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
UserSerVice userService=(UserSerVice)context.getBean("userService");
userService.add();
4.属性的setter方法
UserSerVice:
private UserDao userDao;
setter
applicationContext.xml:
<property name="userDao" ref="userDao">
5.构造方法
applicationContext.xml:
<constructor-arg name="userDao" ref="userDao">
UserSerVice:
private UserDao userDao;
构造方法
4.基于注解的Ioc
1.applicationContext.xml:
<context:component-scan base-package="com.tjetc"></context:component-scan>
2.类配置组件的扫描com.tjetc本包及其子孙包下的所有的在类上标注有@Controller,@Service,@Repository,@Component注解的类,
spring会把标注了这些注解的类当做你配置bean节点一样纳入spring容器管理
5.代理的本质:在不改变目标类方法的代码的情况下对目标类的方法进行增强
6.静态代理
由程序员创建代理类在程序运行前代理类的.class文件就已经存在了.
静态代理需要以下角色
1.接口
目标类和代理类都要实现该接口
2.目标类
被代理的类
3.代理类
代理目标类的类
4.测试类
创建目标对象
创建代理对象(注入目标对象)
调用代理类的方法
7.动态代理:在程序运行时运用反射机制动态创建而成,不是提前写好的,是后期动态生成的
1.JDK动态代理
1、 新建一个接口
2、 为接口创建一个实现类(就是被代理的类)
3、 创建中间类实现java.lang.reflect.InvocationHandler接口 重写invoke方法(Object proxy,Method method,Object[] args) Object invoke=method.invoke(obj,args);
4、 测试 UserSerVice userService=(UserSerVice)Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),new JdkHandler(obj));
2.CGLIB
1.pom.xml cglib
2.创建目标类
3.写方法拦截器: MethodInterceptor intercept(Object proxy,Method method,Object[] args,MethodProxy methodProxy){
Object result=methodProxy.invokeSuper(proxy,args);
}
4.测试类
1.创建目标类对象
2.Enhancer enhancer=new Enhancer();
enhancer.setSuperClass(UserSerVice.class);
enhancer.setCallback(new MyInterceptor(obj));
UserSerVice proxy=(UserSerVice)enhancer.create();
proxy.add();
8.aop
1.aop
2.join point 连接点
3.point cut 切点
4.aspect 切面=切点+增强
5.advice 增强
9.xml aop
1.切面类
2.配置
<!--配置目标类-->
<bean id="userService" class="com.tjetc.service.UserService"></bean>
<!-- 配置切面类-->
<bean id="myAspect" class="com.tjetc.aspect.MyAspect"></bean>
<!-- aop配置切面-->
<aop:config>
<!-- 配置切面-->
<aop:aspect id="myaop" ref="myAspect">
<!-- 配置切点 expression定位到连接点(目标类的方法)的条件表达式-->
<aop:pointcut id="mycut" expression="execution(* com.tjetc.service..*.*(..))"/>
<!-- 配置增强-->
<!-- <aop:before method="doBefore" pointcut-ref="mycut"></aop:before>-->
<!-- <aop:after-returning method="doAfterReturning" pointcut-ref="mycut"></aop:after-returning>-->
<!-- <aop:after method="doAfter" pointcut-ref="mycut"></aop:after>-->
<!-- <aop:after-throwing method="doAfterThrowing" pointcut-ref="mycut"></aop:after-throwing>-->
<aop:around method="doAround" pointcut-ref="mycut"></aop:around>
</aop:aspect>
</aop:config>