说明:文中加粗表示重点,标题已经小标题除外。
Day1
JavaEE三层技术:web层、service层、dao层
每一层所使用的技术:
web:Servlet+JSP ->SpringMVC或者Struts2(已经不怎么用了),一般都用SpringMVC
service:JavaBean
dao:JDBC+DBUtils ->可以用框架MyBatis取代(对于数据库的操作),Hibernate(很老了)也可以
Spring是贯穿三层的技术,比较重要
SSH:Spring + Struts2 + Hibernate(不怎么常用了)
SSM:Spring + SpringMVC + MyBatis (现在比较常用)
Spring其实是一个容器,用来管理对象。包括了new对象、销毁对象、获取对象。
JavaBean的规范:
1.成员变量私有化,提供get/set方法
2.提供无参构造器
3.重写toString、equals、hashCode方法
4.不能用final修饰
快速搭建Spring容器:
1.导包
2.创建类
3.配置文件 --配置管理对象 —bean
a.导入约束
b.创建文件xml —引入约束内容 (src/applicationContext.xml)
c.管理对象
xml文件中的标签标示有很多对象,导入约束后会有很多xml,xmlns等;标示一个对象
4.开启容器获得对象,详细看代码
// 1.开启容器
//一般看见名字很长的
//ClassPath默认是src文件夹下
ClassPathXmlApplicationContext ac =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.获得对象
//方法1
User u1 = (User) ac.getBean("user"); // bean的名字
User u2 = (User) ac.getBean("user"); // bean的名字
User u3 = (User) ac.getBean("user"); // bean的名字
// 方法2,只适用于容器中只有一个User对象
//User u2 = ac.getBean(User.class);
System.out.println(u2);
//== 判断的是地址是否相同,也就是是否为同一个对象
System.out.println(u2 == u1);//结果返回true,因为容器就创建好了一个对象(单例子模式),你调用就返回,因此是同一个对象
ac.close();
Spring核心思想/核心模块/两个重要的组成部分:IOC AOP
IOC(inverse of control):反转控制------传统new对象的工作,交给容器来做;并通过反射的原理,调用类的构造器(默认是无参构造器);对象的属性/依赖注入也交给Spring容器来做。
DI思想:依赖注入
方法有:依赖注入
构造器注入
set方法注入
字段注入
AOP:
Spring管理对象:默认是容器启动就创建好对象,并采用单例模式,因此只创建一个对象,每次调用就返回。当然也可以使用prototype(多例模式),使用对象时会返回多个对象。
Spring创建对象的3种方式:
第一种方式是简单的无参构造器创建对象
第二种静态工厂方法,由于是createUser()是静态方法,因此可以直接用类调用
其中第3种工厂方法创建对象时,由于getUser()是普通方法,调用时需要对象,因此需要先创建一个工厂bean(工厂对象),然后使用factor-bean属性调用创建方法。
代码示例如下:
<!--1. 通过无参构造器创建对象 -->
<bean class="b_create.User" name="user"></bean>
<!-- 工厂:抽象工厂、简单工厂、工厂方法 -->
<!--2. 静态工厂的方式创建对象 -->
<bean class="b_create.StaticFactory" name="user1"
factory-method="createUser"></bean>
<!-- 3.工厂方法 -->
<bean name="factory" class="b_create.StaticFactory"></bean>
<bean name="user2" factory-method="getUser"
factory-bean="factory"></bean>
<!-- ----------------------------------------------------------------------------->
public class StaticFactory {
// 提供静态方法,获得user对象
public static User createUser() {
return new User();
}
// 工厂方法,提供一个普通方法,获得user对象
public User getUser() {
return new User();
}
}
set注入方式引用类型和简单类型
set注入方式需要类有set方法,然后用property标签实现基本类型属性的注入。当属性是一个对象时,首先需要创建一个对象bean,然后采用引用的方式ref来注入属性。示例代码如下:
<!-- 注入1:set方式 -->
<bean class="c_inject.User" name="user">
<!-- 简单类型,都是直接赋值
简单类型:String 八大基本数据类型/包装类
-->
<property name="name" value="lucy"></property>
<property name="age" value="18"></property>
<property name="sex" value="f"></property>
<!-- 引用类型的注入 -->
<property name="car" ref="car"></property>
</bean>
<!-- 注册car对象 -->
<bean name="car" class="c_inject.Car">
<property name="name" value="兰博基尼"></property>
<property name="color" value="黄色"></property>
</bean>
其他三种注入方式
构造器注入了解,其中P命名空间与SPEL表达式注入基本不用
<!-- 方式2:构造器注入 -->
<bean name="user1" class="c_inject.User">
<!-- 全参 -->
<constructor-arg type="java.lang.String" value="tom"></constructor-arg>
<constructor-arg type="int" value="20"></constructor-arg>
<constructor-arg type="char" value="m"></constructor-arg>
<constructor-arg type="c_inject.Car" ref="car"></constructor-arg>
</bean>
<bean name="user2" class="c_inject.User">
<!-- name, age | String , int, 默认只看类型
index属性:表示当前参数是构造器中第几个参数
-->
<constructor-arg type="java.lang.String" value="jack"></constructor-arg>
<constructor-arg type="Integer" value="21" index="0"></constructor-arg>
</bean>
<!-- 方式3:p命名空间注入 - 先添加p命名约束 -->
<bean name="user3" class="c_inject.User"
p:age="23" p:name="rose" p:sex="f"
p:car-ref="car" ></bean>
<!-- 方式4:SPEL表达式注入,引用其他对象的属性 -->
<bean name="user4" class="c_inject.User">
<property name="name" value="#{user3.name}"></property>
</bean>
复杂类型注入
复杂类型主要是类中包含了List,Set,Map,Property等类型,需要进行注入。一般在property标签下面会有这些类型,按照给定格式进行注入即可。其中注意property和Map一起都是以键值对的形式存值的。
示例代码如下;
<bean name="user" class="d_comp.User">
<!-- 如果数组中只有一个元素,可以使用value -->
<!-- <property name="arr" value="11"></property> -->
<property name="arr">
<array>
<value>11</value>
<value>12</value>
<value>13</value>
<!-- <ref bean=""/> -->
</array>
</property>
<property name="list">
<list>
<value>lucy</value>
<value>tom</value>
<value>jack</value>
</list>
</property>
<!-- <property name="set" ref="car"></property> -->
<property name="set">
<set>
<ref bean="car"/>
<ref bean="car1"/>
</set>
</property>
<property name="pros">
<props>
<prop key="driver">com.mysql.jdbc.Driver</prop>
<prop key="username">root</prop>
</props>
</property>
</bean>
<bean name="car" class="d_comp.Car">
<property name="name" value="玛莎拉蒂"></property>
<property name="color" value="绿色"></property>
</bean>
<bean name="car1" class="d_comp.Car">
<property name="name" value="劳斯莱斯"></property>
<property name="color" value="紫色"></property>
</bean>
Day2
一、注解配置
注解用来取代配置文件 —context
a.导包:spring-aop
b.添加命名空间/约束
1.eclipse先导入约束文件 context
2.配置文件中引入约束
c.开启注解配置
详细过程:
1.首先需要在applicationContext.xml配置文件中开启注解扫描
<!-- 开启注解扫描
base-package:基本扫描包,包中的注解才能识别
com.zzxx.crm.web
com.zzxx.crm.service
com.zzxx.crm.dao
-->
<context:component-scan base-package="a_annotation"></context:component-scan>
2.在需要管理的类前加上注解,即可使用该类,其中包括了变量的注入
@Component("u1") // spring容器中就已经管理了user对象,自动命名user
// @Repository // dao
// @Service // service
// @Controller // web
@Scope("singleton") // bean-scope属性
public class User {
private String name;
@Value("18")
private int age;
@Value("f")
private char sex;
/*
* @Autowired // 自动装配 - bean-ref,一般会自动注入进来
* @Qualifier("car1") 指定注入的对象名 bean-name
@Resource(name = "car1") // 取代上面两个注解
private Car car; // 引用类型
public User() {
super();
}
@Value("lucy") // 简单类型的注入
// 严格符合set注入的思想,但是为了方便起见,都会直接使用在变量上
public void setName(String name) {
this.name = name;
}
@PostConstruct // init-method
public void init () {
}
@PreDestroy // destroy-method
public void destroy() {
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
......
二、Spring对Junit的支持
在JUnit的tset方法运行之前,开启容器,并且把需要的对象注入进来
a.导包: spring-test, spring-aop,JUnit
b.SpringJUnit4ClassRunner
示例代码:
// JUnitTest运行之前打开容器
@RunWith(SpringJUnit4ClassRunner.class)
// 指定配置文件路径
@ContextConfiguration("classpath:b_junit/applicationContext.xml")
public class JUnitTest {
@Autowired
private User user;
@Test
public void test02() {
System.out.println(user);
}
@Autowired
private Car car;
@Test
public void test03() {
System.out.println(car);
}
}
三、AOP:面向切面编程 -----代理模式
AOP的一些基本概念:
即AOP面向切面编程表示多个service之间在纵向有公共部分,因此在横向添加一些公共的代码,来实现增强代码的目的。
代理模式:目的是生成代理对象,并对被代理对象的方法进行增强
动态代理:代理对象和被代理对象拥有相同的父接口
cglib代理:代理对象继承被代理对象(被代理对象不能是final)
代码示例:
1.ProxyDemo类,用来添加代理,并实现被代理对象的方法的增强。
public class ProxyDemo {
@Test
// 动态代理 =》观光代码
public void test01() {
// 动态代理的原理:代理对象和被代理对象拥有相同的父接口
// 被代理对象UserServiceImpl
// newProxyInstance获得代理对象
// 代理对象:包含了原来的方法,并且将原来的方法进行了增强
/* loader:类加载器,被代理对象的类加载器
* interfaces:被代理对象的超级接口
* InvocationHandler:执行方法的处理器
*/
UserService us = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(UserServiceImpl.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(),
new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 要增强的方法
* @param args 调用方法的参数
* @return 增强后的方法返回值,原来方法的返回值
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 公共代码
System.out.println("开启事务");
// 执行原来的方法
Object o = method.invoke(us, args);
System.out.println("提交事务");
return o;
}
});
// proxy.transfer();
// us.transfer();
// System.out.println(us.addUser());
System.out.println(proxy.addUser());
System.out.println(proxy instanceof UserServiceImpl);
}
@Test
// CGlib 代理
public void test02() {
// CGlib 代理原理:代理对象继承被代理对象
}
}
2.公共父接口
public interface UserService {
void transfer();
int addUser();
}
3.被代理对象-----实现父接口的类
public class UserServiceImpl implements UserService {
@Override
public void transfer() {
System.out.println("转账操作");
}
@Override
public int addUser() {
System.out.println("添加用户");
return 10;
}
}
四、SpringAOP准备
SpringAOP名词解释:
Joinpoint(连接点):目标对象中,所有可以增强的方法
Pointcut(切入点):目标对象中,已经增强的方法
Advice(通知/增强):增强的代码
Target(目标对象):被代理的对象
Weaving(织入):将通知应用到切入点的过程
aspect(切面):切入点+通知
SpringAOP配置文件过程:
1.配置目标对象
2.配置通知
3.准备织入,形成切面
a.配置切入点
b.织入通知
示例代码:
1.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
<!-- 1.配置目标对象 -->
<bean class="e_springaop.UserServiceImpl" name="userService"></bean>
<!-- 2.配置通知 -->
<bean class="e_springaop.MyAdvice" name="myAdvice"></bean>
<!-- 3.准备织入,形成切面 -->
<!-- 准备工作:导包(aop/aspects/weaver/aopalliance)、引入约束aop(命名空间中的aop约束) -->
<aop:config>
<!-- 配置切入点-要增强什么方法
void e_springaop.UserServiceImpl.insertUser(String)
* e_springaop.UserServiceImpl.insertUser(String)
* e_springaop.UserServiceImpl.*(String)
* e_springaop.UserServiceImpl.*(..)
* e_springaop.*ServiceImpl.*(..)
使用通配符来修改
-->
<aop:pointcut expression="execution(* e_springaop.*ServiceImpl.*(..))" id="pc"/>
<!-- 织入 -->
<aop:aspect ref="myAdvice">
<aop:before method="before" pointcut-ref="pc"/>
<aop:after method="after" pointcut-ref="pc"/>
<aop:after-returning method="afterReturn" pointcut-ref="pc"/>
<aop:after-throwing method="afterThrow" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</beans>
2.通知类
// 通知类
// - 前置通知 切入点之前执行
// - 后置通知 切入点之后执行
// - 环绕通知 切入点执行之前、之后都执行
// - 后置通知 切入点方法正常执行结束后才执行的
// - 异常通知 捕获到切入点异常执行
public class MyAdvice {
// 前置通知 - 在连接点调用之前执行的
public void before() {
System.out.println("前置通知");
}
public void after() {
System.out.println("后置通知1");
}
public void afterReturn() {
System.out.println("后置通知2");
}
public void afterThrow() {
System.out.println("捕获到异常通知");
}
}
3.测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:e_springaop/applicationContext.xml")
public class SpringAOPTest {
@Resource(name="userService")
private UserService userService;
@Test
public void test01() {
userService.findUserById();
}
}
接口类和被代理类与上面的例子类似,不再赘述。
五、JDBC模板使用
Spring和数据库进行整合的模板
JDBC --JdbcTemplate --类,操作数据库
Hibernate – HibernateTemplate
MyBatis
使用JdbcTemplate模板,首先需要导包— pring-jdbc、spring-tx
部分示例代码:
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
// @Resource(name="queryRunner") -- 没法处理事务
// private QueryRunner queryRunner;
@Resource(name="jdbcTemplate")
private JdbcTemplate jt;
public void decrease(int fromId, double money) {
String sql = "update account set money = money - ? where id = ?";
jt.update(sql, money, fromId);
}
public void increase(int toId, double money) {
String sql = "update account set money = money + ? where id = ?";
jt.update(sql, money, toId);
}
}
Day3
Spring事务管理。。。。。后续再细细了解
Maven第一天笔记 -----一个用java写的管理平台,用jar索引来管理jar包,非常方便
1.Maven目录结构
bin —工具/命令
boot —支持包
conf —配置文件,settings.xml
lib —库类 jar
Maven中央仓库地址: https://mvnrepository.com/
2.Maven配置
首先下载Maven,然后在本地创建一个文件夹,名称为repository。然后修改maven文件夹下conf文件夹下的settings.xml配置,把其中的D:/apache-maven-3.6.3/repository从注释中取出来,然后改成自己刚刚建的本地仓库路径即可。
然后将Maven与eclipse绑定即可使用。
3.maven工程目录结构
target:编译后的文件存储目录
src:源代码
main:真正的Java源代码/配置文件放在这边
webapp:以前的webContent
resources:以前放在src中的配置文件
java:以前的src.存放java源代码
(resources/java最终编译路径是合并的)
test:所有的Junit测试都放在这边
pom.xml:maven核心配置文件,用来添加插件、添加jar包
4.maven生命周期(了解)