项目开发: 视图层 (接收参数处理), 业务层 (处理业务), 持久层 (处理数据)
分层架构: 其实就是将 代码分类 , 按功能/职责划分为3类分别存放在web,service,dao包中
1.数据层
UserMapper接口
package com.xjggb.mapper;
public interface UserMapper {
/*
* 保存用户
* */
void save();
}
实现类
package com.xjggb.mapper.impl;
import com.xjggb.mapper.UserMapper;
public class UserMapperImpl implements UserMapper {
@Override
public void save() {
System.out.println("保存成功" );
}
}
2.业务层
接口文件
package com.xjggb.service;
public interface UserService {
void save();
}
接口实现类
package com.xjggb.service.impl;
import com.xjggb.mapper.UserMapper;
import com.xjggb.mapper.impl.UserMapperImpl;
public class UserServiceImpl implements UserMapper {
private UserMapperImpl userMapper = new UserMapperImpl();
@Override
public void save() {
userMapper.save();
}
}
3.视图层
package com.xjggb.controller;
import com.xjggb.service.impl.UserServiceImpl;
public class UserController {
private UserServiceImpl userService = new UserServiceImpl();
public void show(){
userService.save();
}
}
1.当实体类丢失,java文件将无法编译整个项目都报错
2.代码耦合度过高
切换实现类
package com.xjggb.mapper.impl;
import com.xjggb.mapper.UserMapper;
public class DaoUser implements UserMapper {
@Override
public void save() {
System.out.println(" w我是切换的实现类");
}
}
从代码中可以看出需要修改 private UserMapper userMapper = new DaoUser();对象
代码量十分大,成本太高
package com.xjggb.service.impl;
import com.xjggb.mapper.UserMapper;
import com.xjggb.mapper.impl.DaoUser;
import com.xjggb.mapper.impl.UserMapperImpl;
public class UserServiceImpl implements UserMapper {
private UserMapper userMapper = new DaoUser();
@Override
public void save() {
userMapper.save();
}
}
这个时候我们设计一个set注入,就会发生质变
package com.xjggb.service.impl;
import com.xjggb.mapper.UserMapper;
public class UserServiceImpl implements UserMapper {
private UserMapper userMapper ;
public void setUserMapper(UserMapper userMapper){
this.userMapper=userMapper;
}
@Override
public void save() {
userMapper.save();
}
}
之前的代码需要主动的创建对象,控制权在程序元的手中,使用set注入后程序不再主动性,变得被动接收对象我们程序员不再管对象的创建,系统的耦合性大大降低可以专注与业务,这就是IOC模型
小结
三层架构存在的问题?
代码耦合度过高有哪些例子
AOP: 提供了符合AOP要求的面向切面的编程实现
Aspects: 提供了与AspectJ的集成功能
Instrumentation: 提供了类植入(Instrumentation)的支持和类加载器的实现
Messaging: 用于构建基于消息的应用程序
1.Spring是什么?
2.Spring的优点
IOC(Inversion Of Control): 将对象的创建(控制)转交给第三方(工厂)完成, 也叫 控制反转
项目名 hello-spring
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.2.RELEASEversion>
dependency>
dependencies>
package com.xjggb.entity;
public class User {
private Integer id;
private String username;
private String sex;
private String address;
public String toString() {
return "User{id = " + id + ", username = " + username + ", sex = " + sex + ", address = " + address + "}";
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.xjggb.entity.User" >
<property name="id" value="1"/>
<property name="username" value="123"/>
<property name="sex" value="456"/>
<property name="address" value="789"/>
bean>
beans>
package com.xjggb;
import com.xjggb.config.BeanFactory;
import com.xjggb.controller.UserController;
import com.xjggb.entity.User;
import com.xjggb.mapper.impl.DaoUser;
import com.xjggb.mapper.impl.UserMapperImpl;
import com.xjggb.service.UserService;
import com.xjggb.service.impl.UserServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
public class Test01 {
public static void main(String[] args) throws IOException {
/*
* 创建Bean容器
* */
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
/*
* 获取对象
* */
User user = (User) context.getBean("user");
System.out.println("user = " + user);
}
}
1.使用IOC容器需要添加那些依赖
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.2.RELEASEversion>
dependency>
2.配置文件中需要声明定义标签对象?
如何创建IOC容器 配置文件开始加载的时候容器开始创建
new ClassPathXmlApplicationContext("application.xml");
3.注意 给属性注入值 如:
bean的标签属性
属性 | 说明 |
---|---|
id | 对象的引用名称;一定要唯一; 一次只能定义一个引用名称 |
name | 对象的引用名称; 与id区别是:name一次可以定义多个引用名称。 |
class | 类的全限定名称 |
init-method | 指定类中初始化方法的名称,在构造方法执行完毕后立即执行【了解】 |
destroy-method | 指定类中销毁方法名称,在销毁spring容器前执行【了解】 |
lazy-init | 设置为true表示在第一次使用对象的时候才创建,只对单例对象有效。 |
scope | 设置bean的作用范围, 取值: singleton:单例, 默认值; prototype:多例 request:web项目中,将对象存入request域中【了解】 session:web项目中,将对象存入session域中【了解】 globalsession:web项目中,将对象应用于集群环境,没有集群相当于session【了解】 |
<alias name="user" alias="userNew"/>
<bean id="user" class="com.xjggb.entity.User" >
<property name="id" value="1"/>
<property name="username" value="123"/>
<property name="sex" value="456"/>
<property name="address" value="789"/>
</bean>
这个import。一般用于团队开发使用,它可以将多个配置文件,导入合并为一个。
假设,现在项目中有多个人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
合并成一个
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
//合并多个配置文件
<import resource="userApplicayion.xml"/>
<import resource="application.xml"/>
beans>
<bean id="user01" class="com.xjggb.entity.User" p:username="来了老弟" scope="singleton"/>
<bean id="user02" class="com.xjggb.entity.User" c:username="哈哈" scope="prototype"/>
<bean id="user" class="com.xjggb.entity.User" init-method="init" destroy-method="destoy" lazy-init="true"/>
测试
package com.xjggb.test;
public class Test04 {
public static void main(String[] args) {
/*
*创建容器
* */
ClassPathXmlApplicationContext classPath = new ClassPathXmlApplicationContext("application.xml");
/*
* 获取对象
* */
User user = classPath.getBean("user", User.class);
System.out.println("user = " + user);
/*
* 销毁对象
* */
classPath.close();
}
}
1.多个配置文件合并后,我们使用总的配置文件就行了
2.给bean的属性使用property标签注入值必须给属性添加set方法
3.bean的声明周期
4.bean的创建,默认是单例
小结:
配置文件
<bean id="user" class="com.xjggb.entity.User" >
<constructor-arg index="0" value="1"/>
<constructor-arg index="1" value="来了老弟"/>
<constructor-arg index="2" value="男"/>
<constructor-arg index="3" value="噢噢噢噢"/>
bean>
测试
package com.xjggb;
public class Test01 {
public static void main(String[] args) throws IOException {
/*
* 创建Bean容器
* */
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
/*
* 获取对象
* */
User user = (User) context.getBean("user");
System.out.println("user = " + user);
}
}
1.简单注入
package com.xjggb.entity;
public class User {
private Integer id;
private String username;
private String sex;
private String address;
省略get()set()方法tostring()方法
}
2.配置文件
<bean id="mapper" class="com.xjggb.entity.Mapper">
<property name="name" value="我是行健乖乖霸"/>
bean>
3.测试
package com.xjggb.test;
import com.xjggb.entity.Mapper;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test02 {
public static void main(String[] args) {
/*
*创建容器
**/
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
Mapper mapper = context.getBean("mapper", Mapper.class);
System.out.println("mapper = " + mapper);
}
}
4.完善注入
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="mapper" class="com.xjggb.entity.Mapper">
<property name="name" value="我是行健乖乖霸"/>
<property name="books">
<array>
<value>农院路美食街value>
<value>建政路美食街value>
<value>中山路美食街value>
<value>南铁路美食街value>
array>
property>
<property name="hobbies">
<list>
<value>吃饭value>
<value>学习value>
<value>打游戏value>
<value>敲代码value>
list>
property>
<property name="card">
<map>
<entry key="身份证" value="123456"/>
<entry key="学号" value="1838110328"/>
map>
property>
<property name="games" >
<set>
<value>刺激战场value>
<value>王者荣耀value>
<value>部落冲突value>
set>
property>
bean>
beans>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user01" class="com.xjggb.entity.User" p:username="来了老弟"/>
<bean id="user02" class="com.xjggb.entity.User" c:username="哈哈"/>
测试:
public class Test03 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
User user01 = context.getBean("user01", User.class);
System.out.println("user01 = " + user01);
User user02 = context.getBean("user02", User.class);
System.out.println("user02 = " + user02);
}
}
1.掌握set方法注入
2.c命名空间注入和p命名注入 需要添加约束
注意:
1.构造器注入需要添加有参和无参构造
2.set注入记得添加set方法
在Spring中有三种装配的方式:
//创建一个猫类
class Cat {
public void show(){
System.out.println("喵喵");
}
//创建一个狗类
public class Dog {
public void show(){
System.out.println("汪汪");
}
//一个人有两个动物
public class People {
private String name;
private Cat cat;
private Dog dog;
//省略getset方法
配置文件
<bean id="cat" class="com.xjggb.entity.Cat"/>
<bean id="dog" class="com.xjggb.entity.Dog"/>
<bean id="people" class="com.xjggb.entity.People">
<property name="name" value="来了老弟"/>
<property name="cat" ref="cat"/>
<property name="dog" ref="dog"/>
bean>
测试
public class Test05 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
People people = context.getBean("people", People.class);
Dog dog = people.getDog();
dog.show();
Cat cat = people.getCat();
cat.show();
}
<bean id="people" class="com.xjggb.entity.People" autowire="byName">
<property name="name" value="来了老弟"/>
bean>
<bean id="people" class="com.xjggb.entity.People" autowire="byType">
<property name="name" value="小白莲"/>
bean>
<contxt:component-scan base-package="com.xjggb"/>
@Component
public class Cat {
public void show(){
System.out.println("喵喵");
}
}
@Component
public class Dog {
public void show(){
System.out.println("汪汪");
}
}
@Component
public class People {
private String name;
@Autowired
private Cat cat;
@Autowired
private Dog dog;
}
测试
package com.xjggb.test;
import com.xjggb.entity.Cat;
import com.xjggb.entity.Dog;
import com.xjggb.entity.People;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test05 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
People people = context.getBean("people", People.class);
Cat cat = people.getCat();
cat.show();
}
}
@Component
public class People {
/**
* @Autowired: 修饰属性, 方法
* 作用: 给属性注入一个容器中已经存在的对象
*
* 特点: 可以根据属性类型+属性名称注入值
* * @Value: 修饰属性
* * 作用: 给属性注入一个固定的参数值 (包括配置中的参数)
* *
*/
@Value("行健乖乖霸")
private String name;
@Autowired
private Cat cat;
@Autowired
private Dog dog;
提供代理类 控制(拦截)外部对目标对象的访问 的一种代码设计
角色分析:
1.创建接口
package proxy;
public interface Star {
/*
* 唱歌
* */
void sing(Integer meney);
/*
* 拍戏
* */
void pay(Integer money);
}
2.创建目标类(刘德华)
package proxy;
public class LiuStar implements Star {
@Override
public void sing(Integer meney) {
System.out.println("刘德华唱歌真好听, 收费: "+meney);
}
@Override
public void pay(Integer money) {
System.out.println("刘德华拍戏棒棒哒, 收费: "+money);
}
}
3.创建代理类(经济人)
package proxy;
public class LiuStarProxy implements Star {
private Star star ;
public void setLiuStar(Star star){
this.star=star;
}
@Override
public void sing(Integer meney) {
show();
star.sing(meney);
}
@Override
public void pay(Integer money) {
//对方法进行加强
show();
test01();
star.pay(money);
}
public void test01(){
System.out.println("中间添加l电影收费");
System.out.println("中间添加了代言提成");
}
public void show(){
System.out.println("对方法进行加强了");
}
}
4.测试
package com.xjggb.test;
import proxy.LiuStar;
import proxy.LiuStarProxy;
import proxy.Star;
public class Test06 {
public static void main(String[] args) {
/*
* 刘德华懂唱歌
*拍戏
* */
LiuStar liuStar = new LiuStar();
/*
* 代理类 也就是经济人
* */
LiuStarProxy liuStarProxy = new LiuStarProxy();
liuStarProxy.setLiuStar(liuStar);
/*
* 不需要直接找到刘德华说谈拍戏或者唱歌
* 只需要找经济人即可
* 然后经济人可以从中做手脚,
* */
liuStarProxy.pay(123);
liuStarProxy.sing(123);
}
}
小结:
1.代理模式的好处
2.缺点:
动态代理和静态代理角色一样
动态代理的代理类是动态生成的,不是我们直接写好的!
动态代理分为两大类:基于接口的动态代理,基于类的动态代理
1.接口
package proxy;
public interface Star {
/*
* 唱歌
* */
void sing(Integer meney);
/*
* 拍戏
* */
void pay(Integer money);
}
2.创建目标类(刘德华)
package proxy;
public class LiuStar implements Star {
@Override
public void sing(Integer meney) {
System.out.println("刘德华唱歌真好听, 收费: "+meney);
}
@Override
public void pay(Integer money) {
System.out.println("刘德华拍戏棒棒哒, 收费: "+money);
}
}
3.动态代理类
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
private Object star;
public void setObject(Object star){
this.star=star;
}
public Object getProxy(){
return Proxy.newProxyInstance(
this.getClass().getClassLoader(),
star.getClass().getInterfaces(),
this
);
}
/**
* 当代理方法被调用会触发该方法
* @param proxy 代理对象
* @param method 方法
* @param args 参数
* @return 方法返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/*
* 获取参数
* */
show01();
Integer arg = (Integer) args[0];
if(arg>123){
//调用invoke方法
Object invoke = method.invoke(star, args);
return invoke;
}else {
System.out.println("经费不够");
}
return null;
}
//增强方法
public void show01(){
System.out.println("我是经济人吞了一半的经费");
}
}
4.测试
package com.xjggb.test;
import proxy.LiuStar;
import proxy.ProxyInvocationHandler;
import proxy.Star;
public class Test08 {
public static void main(String[] args) {
/*
* 真实对象
* */
LiuStar liuStar = new LiuStar();
/*
* 代理类
* */
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setObject(liuStar);
/*
* 获取代理对象
* */
Star proxy = (Star) proxyInvocationHandler.getProxy();
proxy.pay(123);
}
}
cglib动态代理的案例
官方API
public static Object create(
// 1. 代理对象需要继承的类
java.lang.Class superclass,
// 2. 代理对象需要实现的接口
java.lang.Class[] interfaces,
// 3. 代理对象方法调用时的处理器 InvocationHandler
Callback[] callbacks
)
代理类
/**
* 演示: Cglib动态代理
* 1. 目标对象可以不实现接口
*/
@Test
public void testCglib(){
LiuStar liuStar = new LiuStar();
// 1. 创建代理对象
Star star = (Star) Enhancer.create(
// 1. 需要继承的父类字节码
LiuStar.class,
// 2. 接口字节码数组 (非必须传递接口)
new Class[]{
/*Star.class*/ },
// 3. 方法调用处理器
new org.springframework.cglib.proxy.InvocationHandler() {
/**
* 当代理方法被调用会触发该方法
* @param proxy 代理对象
* @param method 方法
* @param args 参数
* @return 方法返回值
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Integer money = (Integer) args[0];
if(money > 10000){
return method.invoke(liuStar, args);
}else {
System.out.println("档期忙!!!");
}
return null;
}
}
);
System.out.println("==========================="+star.getClass());
// 2. 调用代理方法
star.sing(100);
star.pay(10001);
}
(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>hello-springartifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.0.2.RELEASEversion>
dependency>
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.8.13version>
dependency>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-testartifactId>
<version>5.0.2.RELEASEversion>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
dependencies>
project>
public class UserService {
@Override
public void save() {
System.out.println("保存成功");
}
}
public class LogAdvice {
/**
* 日志工具类 (通知类/增强类/切面类).
*
* @author : Jason.lee
* @version : 1.0
*/
/**
* 通知方法/增强方法
*/
public void log(){
System.out.println("日志已经打印...");
}
}
<bean id="service" class="com.xjggb.service.impl.UserServiceImpl"/>
<bean id="logAdvice" class="com.xjggb.log.LogAdvice"/>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.xjggb.service.impl.UserServiceImpl.*(..))"/>
<aop:aspect ref="logAdvice">
<aop:after method="log" pointcut-ref="pt"/>
aop:aspect>
aop:config>
public class Test09 {
public static void main(String[] args) {
ClassPathXmlApplicationContext classContext = new ClassPathXmlApplicationContext("application.xml");
UserServiceImpl service = classContext.getBean("service", UserServiceImpl.class);
service.save();
}
}
applicationContext.xml
<aop:config proxy-target-class="true">
自动记录日志的原理是什么?
两种动态代理Spring是如何选择的?
public interface UserService {
public void add();
public void delete();
public void update();
public void select();
}
指示符 | 示例 | 作用(细粒度) |
---|---|---|
bean | bean(accountService) | 精确到IOC容器的bean |
within | within(com.itheima.xml.service.impl.AccountServiceImpl) | 精确到类 |
execution | execution(public void com.itheima…save(…)) | 精确到方法 |
<bean id="service" class="com.xjggb.service.impl.UserServiceImpl"/>
<bean id="logAdvice" class="com.xjggb.log.LogAdvice"/>
<aop:config proxy-target-class="true">
<aop:pointcut id="pt" expression="bean(*Service)"/>
<aop:aspect ref="logAdvice">
<aop:after method="log" pointcut-ref="pt"/>
aop:aspect>
aop:config>
<aop:pointcut id="pt" expression="execution(* *(..))"/>
<aop:aspect ref="logAdvice">
<aop:after method="log" pointcut-ref="pt"/>
aop:aspect>
aop:config>
*/
public class LogAdvice {
/**
* 通知方法/增强方法
*/
public void log(){
System.out.println("日志已经打印...");
}
public void before(){
System.out.println("前置通知..");
}
public void afterReturning(){
System.out.println("后置通知..");
}
public void afterThrowing(){
System.out.println("异常通知..");
}
public void after(){
System.out.println("异常通知..");
}
}
<bean id="service" class="com.xjggb.service.impl.UserServiceImpl"/>
<bean id="logAdvice" class="com.xjggb.log.LogAdvice"/>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.xjggb.service.impl.UserServiceImpl.*(..))"/>
<aop:aspect ref="logAdvice">
<aop:after method="before" pointcut-ref="pt"/>
<aop:after-returning method="afterReturning" pointcut-ref="pt"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pt"/>
<aop:after method="log" pointcut-ref="pt"/>
aop:aspect>
aop:config>
小结:
1.需要增强的类
public class UserServiceImpl {
public void add() {
System.out.println("增加了一个用户!");
}
public void delete() {
System.out.println("删除了一个用户!");
}
public void update() {
System.out.println("更新了一个用户!");
}
public void select() {
System.out.println("查询了一个用户!");
}
}
2.增强的方法
public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
}
}
public class Log implements MethodBeforeAdvice {
//method: 要执行的目标对象的方法
//args:参数
//target:目标对象
@Override
public void before(Method method, Object[] objects, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
3.配置文件
<!--创建对象放进容器中-->
<bean id="userService" class="com.xjggb.logservice.impl.UserServiceImpl"/>
<bean id="log" class="com.xjggb.logservice.log.Log"/>
<bean id="logAdvice" class="com.xjggb.logservice.log.AfterLog"/>
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.xjggb.logservice.impl.*.*(..))"/>
<!--开启环绕通知-->
<aop:advisor advice-ref="logAdvice" pointcut-ref="pt"/>
<aop:advisor advice-ref="log" pointcut-ref="pt"/>
</aop:config>
4.测试
public class Test10 {
public static void main(String[] args) {
ClassPathXmlApplicationContext classContext = new ClassPathXmlApplicationContext("application.xml");
UserServiceImpl service = classContext.getBean("userService", UserServiceImpl.class);
service.add();
service.delete();
service.select();
service.update();
}
}
小结:
注解配置
1.定义一个增强类
package com.xjggb.logservice.log;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component //将类注入容器交给Spring管理
@Aspect //标志这个类是一个切面类
public class SectionClass {
/**
* 通知方法/增强方法
*/
@Pointcut("execution(* com.xjggb.logservice.impl.UserServiceImpl.*(..))")
public void log(){
System.out.println("日志已经打印...");
}
//方法执行前通知
@Before("log()")
public void before(){
System.out.println("前置通知");
}
@AfterReturning("log()")
public void show01(){
System.out.println("后置通知");
}
//异常通知
@AfterThrowing("log()")
public void AfterThrowing(){
System.out.println("异常通知");
}
//最终通知
@After("execution(* com.xjggb.logservice.impl.UserServiceImpl.*(..))")
public void show(){
System.out.println("最终通知");
}
@Around("log()") //添加切入点
public void show(ProceedingJoinPoint joinPoint){
System.out.println(" 环绕前" );
Signature signature = joinPoint.getSignature();
System.out.println("signature = " + signature);
try {
before();
Object proceed = joinPoint.proceed();
show();
} catch (Throwable throwable) {
throwable.printStackTrace();
AfterThrowing();
}finally {
show();
}
System.out.println();
}
}
2.需要被增强的类
public class UserServiceImpl {
public void add() {
System.out.println("增加了一个用户!");
}
public void delete() {
System.out.println("删除了一个用户!");
}
public void update() {
System.out.println("更新了一个用户!");
}
public void select() {
System.out.println("查询了一个用户!");
}
}
3.配置文件
<context:component-scan base-package="com.xjggb.logservice.log"/>
<aop:aspectj-autoproxy/>
<bean id="userService" class="com.xjggb.logservice.impl.UserServiceImpl"/>
4.测试
public class Test10 {
public static void main(String[] args) {
ClassPathXmlApplicationContext classContext = new ClassPathXmlApplicationContext("application.xml");
UserServiceImpl service = classContext.getBean("userService", UserServiceImpl.class);
service.add();
service.delete();
service.select();
service.update();
}
}
小结
1.请理解以下注解的作用?
2.ProceedingJoinPoint 对象的使用?
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null)
{
//xxxxxx 注解的名字
xxxxxx annoObj= method.getAnnotation(xxxxxx.class);
}
return null;
2.方法2:上面我们已经知道了方法名和类的对象,通过反射可以获取类的内部任何信息。
// 切面所在类
Object target = joinPoint.getTarget();
String methodName = joinPoint.getSignature().getName();
Method method = null;
for (Method m : target.getClass().getMethods()) {
if (m.getName().equals(methodName)) {
method = m;
// xxxxxx annoObj= method.getAnnotation(xxxxxx.class);同上
break;
}
}
事务的作用是什么?
什么是ACID原则?
Atomicity: 原子性: 不可拆分事务中的多个事件: 要么同时成功, 要么同时失败
Consistency: 一致性: 事务执行前后的数据总量保持不变
Isolation: 隔离性: 多个事务之间相对独立, 互不影响
Durability: 持久性: 事务执行之后的结果会永久保存起来
以下隔离级别分别解决了什么问题?
ISOLATION_READ_UNCOMMITTED: 没有解决任何问题 (有脏读问题)
ISOLATION_READ_COMMITTED: 解决了脏读问题
ISOLATION_REPEATABLE_READ: 解决了不可重复读问题
ISOLATION_SERIALIZABLE: 解决了幻读问题
请说出以下传播行为的含义:
REQUIRED: 需要
SUPPORTS: 支持
MANDATORY: 强制
REQUIRES_NEW: 新
NOT_SUPPORTED: 不支持
NEVER: 决不
NESTED: 嵌套
声明式事务的好处是什么?
请描述以下注解的作用?
@EnableTransactionManagement: 修饰类, 开启事务管理功能 (注解支持)
@Transactional: 修饰类, 方法: 给方法添加事务管理功能
Spring的优点有哪些?