org.springframework
spring-webmvc
5.3.9
org.springframework
spring-jdbc
5.3.9
总结:spring就是一个轻量级的控制反转(IOC)和面向切面编程的框架。
核心容器(Spring Core)
核心容器提供Spring框架的基本功能。Spring以bean的方式组织和管理Java应用中的各个组件及其关系。Spring使用BeanFactory来产生和管理Bean,它是工厂模式的实现。BeanFactory使用控制反转(IoC)模式将应用的配置和依赖性规范与实际的应用程序代码分开。
应用上下文(Spring Context)
Spring上下文是一个配置文件,向Spring框架提供上下文信息。Spring上下文包括企业服务,如JNDI、EJB、电子邮件、国际化、校验和调度功能。
面向切面编程(Spring AOP)
AOP(Aspect Oriented Programming)
通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring框架中。所以,可以很容易地使 Spring框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
JDBC和DAO模块(Spring DAO)
JDBC、DAO的抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理,和不同数据库供应商所抛出的错误信息。异常层次结构简化了错误处理,并且极大的降低了需要编写的代码数量,比如打开和关闭链接。
对象实体映射(Spring ORM)
ORM(Object Relational Mapping)
Spring框架插入了若干个ORM框架,从而提供了ORM对象的关系工具,其中包括了Hibernate、JDO和 IBatis SQL Map等,所有这些都遵从Spring的通用事物和DAO异常层次结构。
Web模块(Spring Web)
Web上下文模块建立在应用程序上下文模块之上,为基于web的应用程序提供了上下文。所以Spring框架支持与Struts集成,web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
MVC模块(Spring Web MVC)
MVC(Model View Controller)
MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成为高度可配置的。MVC容纳了大量视图技术,其中包括JSP、POI等,模型来有JavaBean来构成,存放于m当中,而视图是一个街口,负责实现模型,控制器表示逻辑代码,由c的事情。Spring框架的功能可以用在任何J2EE服务器当中,大多数功能也适用于不受管理的环境。Spring的核心要点就是支持不绑定到特定J2EE服务的可重用业务和数据的访问的对象,毫无疑问这样的对象可以在不同的J2EE环境,独立应用程序和测试环境之间重用。
控制反转(IOC),是一种设计思想,DI(依赖注入)是实现IOC 的一种方法。没有IOC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建有程序自己控制,控制反转后将对象的创建转移给第三方。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式,在spring中实现控制反转的是IOC容器,其实现方法是依赖注入。
import一般用于团队开发使用,他可以将多个配置文件导入合并为一个。
依赖:bean对象的创建依赖于容器
注入:bean对象中的属性由容器来注入
环境搭建
1、复杂类型
package com.zjb.pojo;
public class Address {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
2、真实测试对象
package com.zjb.pojo;
import java.util.*;
public class Student {
private String name;
private Address addr;
private String[] books;
private List hobbys;
private Map card;
private Set games;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddr() {
return addr;
}
public void setAddr(Address addr) {
this.addr = addr;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List getHobbys() {
return hobbys;
}
public void setHobbys(List hobbys) {
this.hobbys = hobbys;
}
public Map getCard() {
return card;
}
public void setCard(Map card) {
this.card = card;
}
public Set getGames() {
return games;
}
public void setGames(Set games) {
this.games = games;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", addr=" + addr.toString() +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
3、applicationContext.xml
三国
水浒
钓鱼
打游戏
LoL
CF
www
123
123
4、测试类
import com.zjb.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student stu = (Student) context.getBean("stu");
System.out.println(stu.toString());
}
}
我们可以使用p命名空间和c命名空间进行注入
package com.zjb.pojo;
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
applicationContext.xml
测试类
import com.zjb.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("userBean.xml");
User user = context.getBean("user", User.class);
User user2 = context.getBean("user2", User.class);
System.out.println(user.toString());
System.out.println(user2.toString());
}
}
注意:p命名和c命名空间不能直接使用,需要导入xml约束!
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
作用域 | 描述 |
---|---|
singleton | (默认)将单个 bean 定义范围限定为每个 Spring IoC 容器的单个对象实例。 |
prototype | 将单个 bean 定义范围限定为任意数量的对象实例。 |
request | 将单个 bean 定义范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有自己的 bean 实例,该 bean 实例是在单个 bean 定义的后面创建的。仅在 web-aware Spring 的上下文中有效ApplicationContext 。 |
session | 将单个 bean 定义范围限定为 HTTP 的生命周期Session 。仅在 web-aware Spring 的上下文中有效ApplicationContext 。 |
application | 将单个 bean 定义范围限定为ServletContext . 仅在 web-aware Spring 的上下文中有效ApplicationContext 。 |
websocket | 将单个 bean 定义范围限定为WebSocket . 仅在 web-aware Spring 的上下文中有效ApplicationContext 。 |
单例模式:Spring默认的机制
原型模式:每次从容器中get的时候,都会产生一个新对象。
在Spring中有三种装配方式
小结:
使用注解实现自动装配的前提
2.配置注解的支持
3.全部配置如下
直接在属性上使用,也可以在set方法上使用。
使用Autowired我们可以不用编写set方法,前提是这个自动装配的属性在Spring容器中存在
package com.zjb.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class Person {
@Autowired
private Cat cat;
@Autowired
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解@Autowired完成的时候,我们可以使用@Qualifier(value="xxx")去配合@Autowired的使用,指定一个唯一的bean对象注入
package com.zjb.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Person {
@Autowired
@Qualifier(value = "cat22")
private Cat cat;
@Autowired
@Qualifier(value = "dog22")
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.zjb.pojo;
import javax.annotation.Resource;
public class Person {
@Resource(name="cat22")
private Cat cat;
@Resource(name="dog11")
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public Dog getDog() {
return dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.zjb.pojo;
import org.springframework.stereotype.Component;
/**
* @Component : 组件
* @Component 等价于
*/
@Component
public class User {
private String name = "小三";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.zjb.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* @Component : 组件
* @Component 等价于
*/
@Component
public class User {
/**
* @Value 等价于
* @Value 也可以用在set方法上
*/
@Value("小三")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我们在web开发中,会按照mvc三层架构分层。
这四个注解功能都是一样的,都是代表将某个类注入到Spring容器中,装配bean
package com.zjb.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
* @Scope :作用域
* @Scope 等价于
*/
@Scope("singleton")
@Component
public class User {
@Value("小三")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
xml与注解的最佳实践
package com.zjb.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
@Value("小三")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.zjb.config;
import com.zjb.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
/**
* @Configuration 代表这是一个配置类,相当于applicationContext.xml文件
* @Import 相当于 表示 把配置类合并为一个
* @ComponentScan 相当于 表示要扫描的包路径
*/
@Configuration
@Import(JavaConfig.class)
@ComponentScan("com.zjb.pojo")
public class AppConfig {
/**
* @Bean 注册一个bean,相当于一个bean标签
* 方法的名字,相当于bean标签的id属性
* 方法的返回值,相当于bean标签的class属性
*/
@Bean
public User user(){
return new User();
}
}
import com.zjb.config.AppConfig;
import com.zjb.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
User user = context.getBean("user", User.class);
System.out.println(user.getName());
}
}
角色分析:
实现步骤:
1、抽象角色
package com.zjb.demo1;
/**
* 抽象角色
*/
public interface Rent {
/**
* 租房子
*/
public void rent();
}
2、真实角色
package com.zjb.demo1;
/**
* 真实角色
*/
public class Host implements Rent {
/**
* 出租房子
*/
public void rent() {
System.out.println("房东要出租房子");
}
}
3、代理角色
package com.zjb.demo1;
/**
* 代理角色
*/
public class Proxy implements Rent {
private Host host;
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
/**
* 租房子
*/
public void rent() {
seeHourse();
host.rent();
heTong();
}
public void seeHourse(){
System.out.println("中介带你去看房子");
}
public void heTong(){
System.out.println("签合同");
}
}
4、客户端
package com.zjb.demo1;
/**
* 客户端访问代理角色
*/
public class Client {
public static void main(String[] args) {
Host host = new Host();
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
静态代理模式的好处:
缺点:
一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率变低
需要了解两个类:Proxy:代理、InvocationHandler:调用处理程序
代码实现:
package com.zjb.demo2;
public interface UserService {
void add();
void update();
void delete();
void query();
}
package com.zjb.demo2;
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("新增一个用户");
}
public void update() {
System.out.println("修改一个用户");
}
public void delete() {
System.out.println("删除一个用户");
}
public void query() {
System.out.println("查询一个用户");
}
}
package com.zjb.demo2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public void setTarget(Object target) {
this.target = target;
}
/**
* 获取代理对象
* @return
*/
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
/**
* 处理代理程序
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
printLog(method.getName());
return method.invoke(target,args);
}
public void printLog(String msg){
System.out.println("执行了"+msg+"方法");
}
}
package com.zjb.demo2;
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService);
UserService proxy = (UserService) pih.getProxy();
proxy.delete();
}
}
动态代理的好处:
AOP(Aspect Oriented Programming) 意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可用性,同时提高了开发的效率。
提供声明式事务;允许用户自定义切面。
SSpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice;
通知类型 | 连接点 | 实现接口 |
---|---|---|
前置通知 | 方法前 | org.springframework.aop.MethodBeforeAdvice |
后置通知 | 方法后 | org.springframework.aop.AfterReturningAdvice |
环境通知 | 方法前后 | org.aopalliance.intercept.MethodInterceptor |
异常抛出通知 | 方法抛出异常 | org.springframework.aop.ThrowsAdvice |
引介通知 | 类中增加新的方法属性 | org.springframework.aop.IntroductionInterceptor |
即AOP在不改变原有代码的情况下,去增加新的功能
使用AOP,需要导入一个依赖包
org.aspectj
aspectjweaver
1.9.4
package com.zjb.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class BeforeLog implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了");
}
}
package com.zjb.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"方法完成,返回值"+returnValue);
}
}
package com.zjb.service;
public interface UserService {
void add();
void update();
void delete();
void query();
}
package com.zjb.service;
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("新增一个用户");
}
public void update() {
System.out.println("修改一个用户");
}
public void delete() {
System.out.println("删除一个用户");
}
public void query() {
System.out.println("查询一个用户");
}
}
import com.zjb.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
package com.zjb.diy;
public class DiyLog {
public void before(){
System.out.println("=========方法执行前=============");
}
public void after(){
System.out.println("=========方法执行后=============");
}
}
package com.zjb.service;
public interface UserService {
void add();
void update();
void delete();
void query();
}
package com.zjb.service;
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("新增一个用户");
}
public void update() {
System.out.println("修改一个用户");
}
public void delete() {
System.out.println("删除一个用户");
}
public void query() {
System.out.println("查询一个用户");
}
}
import com.zjb.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
}
package com.zjb.diy;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnoLog {
@Before("execution(* com.zjb.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("========方法执行前==========");
}
@After("execution(* com.zjb.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("========方法执行后==========");
}
}
1、引入依赖
junit
junit
4.12
org.mybatis
mybatis
3.5.2
org.mybatis
mybatis-spring
2.0.6
mysql
mysql-connector-java
8.0.13
org.springframework
spring-webmvc
5.1.3.RELEASE
org.springframework
spring-jdbc
5.1.3.RELEASE
org.aspectj
aspectjweaver
1.9.2
org.projectlombok
lombok
1.18.22
provided
2、mybatis-config.xml
3、User实体类
package com.zjb.pojo;
import lombok.Data;
@Data
public class User {
private Integer id;
private String name;
private String pwd;
}
4、UserMapper
package com.zjb.mapper;
import com.zjb.pojo.User;
import java.util.List;
public interface UserMapper {
List selectUser();
}
5、 UserMapper.xml
6.测试类
import com.zjb.mapper.UserMapper;
import com.zjb.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MyTest {
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
List users = userMapper.selectUser();
for (User user : users) {
System.out.println(user.toString());
}
}
}
7、spring-dao.xml
8、applicationContext.xml
9、 UserMapperImpl
package com.zjb.mapper;
import com.zjb.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import java.util.List;
public class UserMapperImpl implements UserMapper {
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List selectUser() {
return sqlSession.getMapper(UserMapper.class).selectUser();
}
}
7、spring-dao.xml
8、applicationContext.xml
9、 UserMapperImpl
package com.zjb.mapper;
import com.zjb.pojo.User;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
public List selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。