Spring框架基础2
Spring框架基础2
测试Spring的AOP思想和注解的使用
导包(在前面的基础上添加)
SpringAOP名词解释
AOP编程思想:横向重复代码,纵向抽取;就是说多个地方重复的代码可以抽取出来公用(过滤器等可以体现)
动态代理:动态代理可以体现AOP思想;对目标方法进行增强
SpringAOP开发:封装了动态代理代码(包括cglib代理),可以对任何类进行代理增强
Joinpoint(连接点):目标对象中,所有可以增强的方法
Pointcut(切入点):目标对象,已经增强的方法
Advice(通知/增强):增强的代码
Target(目标对象):被代理对象
Weaving(织入):将通知应用到切入点的过程
Proxy(代理):将通知织入到目标对象之后,形成代理对象
aspect(切面):切入点+通知
创建配置文件(如图由上至下)
<?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.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <!-- 配置目标对象 -->
<bean name="userService" class="com.service.UserServiceImpl"></bean>
<!-- 配置通知对象 -->
<bean name="myAdvice" class="com.anno.MyAdvice"></bean>
<!-- 将通知织入目标对象,利用注解实现 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
<?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.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> <!-- 配置目标对象 -->
<bean name="userServiceTarget" class="com.service.UserServiceImpl"></bean>
<!-- 配置通知对象 -->
<bean name="myAdvice" class="com.aspect.MyAdvice"></bean>
<!-- 将通知织入目标对象 -->
<aop:config>
<!-- 配置切入点,即需要加强功能的方法
public void com.service.UserServiceImpl.save()
void com.service.UserServiceImpl.save()
* com.service.UserServiceImpl.save()
* com.service.UserServiceImpl.*
* com.service.UserServiceImpl.*(..)
* com.service.*ServiceImpl.*(..)-->
<aop:pointcut id="pc" expression="execution(* com.service.*ServiceImpl.*(..))"/>
<aop:aspect ref="myAdvice">
<!-- 将myAdvice的before切入到UserServiceImpl.save() -->
<aop:before method="before" pointcut-ref="pc"/>
<aop:after-returning method="afterReturning" pointcut-ref="pc"/>
<aop:around method="around" pointcut-ref="pc"/>
<aop:after-throwing method="afterException" pointcut-ref="pc"/>
<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</beans>
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd "> <!-- 扫描相应包下的类的所有注解 -->
<!-- 会扫描该包下的所有子孙类 -->
<context:component-scan base-package="com.bean"/> <bean name="car2" class="com.bean.Car">
<property name="name" value="玛莎拉蒂"/>
<property name="color" value="red"/>
</bean> </beans>
相应的实体类与接口
package com.bean; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; /**
* @author: XDZY
* @date: 2018/9/5 23:38
* @description: 车辆实体类
*/
@Component("car")
public class Car {
@Value("兰博基尼")
private String name;
@Value("red")
private String color; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getColor() {
return color;
} public void setColor(String color) {
this.color = color;
} @Override
public String toString() {
return "Car{" +
"name='" + name + '\'' +
", color='" + color + '\'' +
'}';
}
}
package com.bean; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource; /**
* @author: XDZY
* @date: 2018/9/5 19:31
* @description: 用户实体类
* 通过注解获取对象
* "@Component("user")==<bean name="user" class="com.bean.User"/>"
*/
@Component("user")
//@Service("user")指定为service层
//@Controller("user")指定为web层
//@Repository("user")指定为dao层
//单例还是多例
//@Scope(scopeName = "singleton")
public class User {
//通过反射设置值,破坏了封装性
@Value("xdzy")
private String name;
@Value("15")
private int age; //自动配置car属性;但是有多个对象时,不知道获取哪个
//@Autowired
//指定哪个对象
//@Qualifier("car2")
//手动注解使用哪个car
@Resource(name = "car2")
private Car car; //创建对象前调用
@PostConstruct
public void init() {
System.out.println("初始化方法");
} //对象销毁前调用
@PreDestroy
public void destroy() {
System.out.println("销毁方法");
} public Car getCar() {
return car;
} public void setCar(Car car) {
this.car = car;
} public String getName() {
return name;
} //通过set设置值,推荐使用
@Value("xdzy")
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 +
", car=" + car +
'}';
}
}
package com.service; /**
* @author: XDZY
* @date: 2018/9/6 20:21
* @description:
*/
public interface UserService {
void save(); void del(); void update(); void find();
}
package com.service; /**
* @author: XDZY
* @date: 2018/9/6 20:22
* @description:
*/
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("增加用户");
} @Override
public void del() {
System.out.println("删除用户");
} @Override
public void update() {
System.out.println("修改用户");
} @Override
public void find() {
System.out.println("查询用户");
}
}
JDK动态代理
package com.service; import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; /**
* @author: XDZY
* @date: 2018/9/6 20:25
* @description: JDK动态代理
* 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术
* 动态代理可对方法进行增强,如增加事务的打开与提交
* 个人理解:它是对service实现类里所有的方法进行了增强;
* 在不破坏原有结构的情况下,生成动态代理对象,对原有方法进行增强
*/
public class UserServiceProxyFactory implements InvocationHandler {
private UserService us; public UserServiceProxyFactory(UserService us) {
this.us = us;
} public UserService getUserServiceProxy() {
//生成动态代理
UserService userProxy = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(),
this);
//返回一个动态代理对象
return userProxy;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("打开事务");
Object invoke = method.invoke(us, args);
System.out.println("提交事务");
return invoke;
}
}
Cglib代理
package com.service; import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /**
* @author: XDZY
* @date: 2018/9/6 20:25
* @description: Cglib动态代理
* 可以对任何类生成代理,对目标对象进行继承代理
*/
public class UserServiceProxyFactory2 implements MethodInterceptor {
public UserService getUserServiceProxy() {
//生成代理对象
Enhancer en = new Enhancer();
//对谁进行代理
en.setSuperclass(UserServiceImpl.class);
//代理要做什么
en.setCallback(this);
//创建代理对象
UserService us = (UserService) en.create();
return us;
} @Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//打开事务
System.out.println("打开事务");
//调用原有方法
Object returnValue = methodProxy.invokeSuper(o, objects);
//提交事务
System.out.println("提交事务");
return returnValue;
}
}
通知类
package com.anno; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*; /**
* @author: XDZY
* @date: 2018/9/7 08:23
* @description: 利用注解实现通知
* "@Aspect:表示该类是一个通知类
*/
@Aspect
public class MyAdvice {
//方便管理切入点
@Pointcut("execution(* com.service.*ServiceImpl.*(..))")
public void pc() {
} //配置通知,并指定织入到哪去
//前置通知:目标方法运行之前
@Before("MyAdvice.pc()")
public void before() {
System.out.println("前置通知");
} //后置通知(如果出现异常不会调用):之后
@AfterReturning("execution(* com.service.*ServiceImpl.*(..))")
public void afterReturning() {
System.out.println("后置通知(如果出现异常不会调用)");
} //环绕通知:之前之后
@Around("execution(* com.service.*ServiceImpl.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知之前部分");
//调用目标方法
Object proceed = pjp.proceed();
System.out.println("环绕通知之后部分");
return proceed;
} //异常拦截通知:出现异常调用
@AfterThrowing("execution(* com.service.*ServiceImpl.*(..))")
public void afterException() {
System.out.println("出现异常调用");
} //后置通知(无论是否出现异常都会调用):之后
@After("execution(* com.service.*ServiceImpl.*(..))")
public void after() {
System.out.println("后置通知(无论是否出现异常都会调用)");
}
}
package com.aspect; import org.aspectj.lang.ProceedingJoinPoint; /**
* @author: XDZY
* @date: 2018/9/7 08:23
* @description: 通知
* 前置通知:目标方法运行之前
* 后置通知(如果出现异常不会调用):之后
* 环绕通知:之前之后
* 异常拦截通知:出现异常调用
* 后置通知(无论是否出现异常都会调用):之后
*/
public class MyAdvice {
//前置通知:目标方法运行之前
public void before() {
System.out.println("前置通知");
} //后置通知(如果出现异常不会调用):之后
public void afterReturning() {
System.out.println("后置通知(如果出现异常不会调用)");
} //环绕通知:之前之后
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知之前部分");
//调用目标方法
Object proceed = pjp.proceed();
System.out.println("环绕通知之后部分");
return proceed;
} //异常拦截通知:出现异常调用
public void afterException() {
System.out.println("出现异常调用");
} //后置通知(无论是否出现异常都会调用):之后
public void after() {
System.out.println("后置通知(无论是否出现异常都会调用)");
}
}
测试类
package com.test; import com.service.UserService;
import com.service.UserServiceImpl;
import com.service.UserServiceProxyFactory;
import com.service.UserServiceProxyFactory2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* @author: XDZY
* @date: 2018/9/6 09:32
* @description: 测试注解获取对象
* "@RunWith:可以帮助我们创建容器,这样xml地址改动,测试方法不用全部修改
* "@ContextConfiguration:指定容器位置
* 注意junit版本问题
*/
//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:resources/applicationContext.xml")
public class Demo1 {
/*@Resource(name = "user")
private User user; @Test
public void test(){
System.out.println(user);
}*/ //JDK动态代理
@Test
public void test1() {
UserService us = new UserServiceImpl();
UserServiceProxyFactory factory = new UserServiceProxyFactory(us);
UserService userProxy = factory.getUserServiceProxy();
userProxy.save(); //代理对象和被代理对象实现了相同的接口(false)
System.out.println(userProxy instanceof UserServiceImpl);
} //Cglib动态代理
@Test
public void test2() {
UserServiceProxyFactory2 factory = new UserServiceProxyFactory2();
UserService userProxy = factory.getUserServiceProxy();
userProxy.save(); //代理对象继承了被代理对象(true)
System.out.println(userProxy instanceof UserServiceImpl);
} //通知织入
@Test
public void test() {
//创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("com/aop/applicationContext.xml");
//获取user对象
UserService userService = (UserService) ac.getBean("userServiceTarget");
userService.save();
} //注解通知织入
@Test
public void test4() {
//创建容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("com/anno/applicationContext.xml");
//获取user对象
UserService userService = (UserService) ac.getBean("userService");
userService.save();
}
}
Spring框架基础2的更多相关文章
- Spring学习指南-第二章-Spring框架基础(完)
第二章 Spring框架基础 面向接口编程的设计方法 在上一章中,我们看到了一个依赖于其他类的POJO类包含了对其依赖项的具体类的引用.例如,FixedDepositController 类包含 ...
- 4-1 Spring框架基础知识
Spring框架基础知识 1.Spring 框架作用 主要解决了创建对象和管理对象的问题. 自动装配机制 2.Spring 框架 (Spring容器,JavaBean容器,Bean容器,Spring容 ...
- Spring框架基础知识
本人博客文章网址:https://www.peretang.com/basic-knowledge-of-spring-framework/ Spring框架简介 Spring , 一个开源的框架 , ...
- Spring框架基础
1 Spring框架 1.1 Spring的基本概念 是一个轻量级的框架,提供基础的开发包,包括消息.web通讯.数据库.大数据.授权.手机应用.session管理 ...
- Spring 框架基础(04):AOP切面编程概念,几种实现方式演示
本文源码:GitHub·点这里 || GitEE·点这里 一.AOP基础简介 1.切面编程简介 AOP全称:Aspect Oriented Programming,面向切面编程.通过预编译方式和运行期 ...
- Spring框架基础解析
Spring是一个轻量级的.非侵入式的容器框架:对Bean对象的生命周期进行管理. Spring框架的核心:IOC(控制反转).DI(依赖注入).AOP(面向切面编程). (1) IOC:控制反转. ...
- Spring 框架基础(06):Mvc架构模式简介,执行流程详解
本文源码:GitHub·点这里 || GitEE·点这里 一.SpringMvc框架简介 1.Mvc设计理念 MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集 ...
- Spring 框架基础(03):核心思想 IOC 说明,案例演示
本文源码:GitHub·点这里 || GitEE·点这里 一.IOC控制反转 1.IOC容器思想 Java系统中对象耦合关系十分复杂,系统的各模块之间依赖,微服务模块之间的相互调用请求,都是这个道理. ...
- Spring 框架基础(02):Bean的生命周期,作用域,装配总结
本文源码:GitHub·点这里 || GitEE·点这里 一.装配方式 Bean的概念:Spring框架管理的应用程序中,由Spring容器负责创建,装配,设置属性,进而管理整个生命周期的对象,称为B ...
随机推荐
- rake 任务参数传递问题解决
原文 : https://robots.thoughtbot.com/how-to-use-arguments-in-a-rake-task namespace :tweets do desc 'S ...
- ZK典型应用场景
1. 数据发布/订阅--动态获取数据 2.Master选举 a). 利用Zk会保证无法重复创建一个已经存在的节点 b). 多个客户端同时创建,创建成功的即是master,并监控master节点,一旦m ...
- genymotion安装及使用出现的问题
此处总结genymotion出现的问题. 1)安装好genymotion后,新建一个模拟器.去下载的时候报错 Unable to create Virtual Device: Connection t ...
- 斗鱼连接弹幕Demo_pythonC#
简明扼要的说下, 就两个线程,一个 负责收数据,一个负责发心跳包. 步骤如下, 进程1,调用 发包函数,发送连接请求,然后再发送 获取弹幕类型请求,就一直循环接收数据. 进程2,循环函数,每隔45秒向 ...
- JS URL解析
function urlParse(url) { try { var hostexp = /http\:\/\/([^\/]+)/; var hoststr = url.match(hostexp)[ ...
- XHTML教会我的一些东西-1
第一次写博客,虽然以前写作文是我的强项,我也很能说,但是似乎现在这种能力正在退化.不知为什么,到了大学之后我就变得跟以前不一样,似乎是回到了小学时的我.我在大学开始变得内向.沉默.不去主动和别人交谈. ...
- Django Rest Framework进阶二
一.版本 版本控制:当程序越来越大,后期需要再加入一些功能或者进行二次开发时就需要加上版本号了. 之前我们在没有接触rest_framework之前一般是以下这种方式来实现的 class UserVi ...
- js获取农历日期【转】
var CalendarData=new Array(100); var madd=new Array(12); var tgString="甲乙丙丁戊己庚辛壬癸"; var dz ...
- Android Recyclerview隐藏item的所在区域显示大空白问题的解决方案
最近搞了下Recyclerview,做了增加.删除item的功能.item上方有卡签 插个图片看下效果,点击底下的添加上去,同时,底下的item消失,这个用notifyItemInserted和not ...
- CSS 笔记之 CSS 选择器
/*先设置背景再设置前景*/ pre{ background-color: #f8f8f8; border: solid 1px #ccc; border-radius: 3px; overflow: ...