标签:win expr isp package creat == 通过 容器 初始
Spring框架基础2
测试Spring的AOP思想和注解的使用
导包(在前面的基础上添加)
SpringAOP名词解释
AOP编程思想:横向重复代码,纵向抽取;就是说多个地方重复的代码可以抽取出来公用(过滤器等可以体现)
动态代理:动态代理可以体现AOP思想;对目标方法进行增强
SpringAOP开发:封装了动态代理代码(包括cglib代理),可以对任何类进行代理增强
Joinpoint(连接点):目标对象中,所有可以增强的方法
Pointcut(切入点):目标对象,已经增强的方法
Advice(通知/增强):增强的代码
Target(目标对象):被代理对象
Weaving(织入):将通知应用到切入点的过程
Proxy(代理):将通知织入到目标对象之后,形成代理对象
aspect(切面):切入点+通知
创建配置文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xmlns="http://www.springframework.org/schema/beans" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans 6 http://www.springframework.org/schema/beans/spring-beans-4.2.xsd 7 http://www.springframework.org/schema/context 8 http://www.springframework.org/schema/context/spring-context-4.2.xsd "> 9 10 <!-- 扫描相应包下的类的所有注解 --> 11 <!-- 会扫描该包下的所有子孙类 --> 12 <context:component-scan base-package="com.bean"></context:component-scan> 13 14 <bean name="car2" class="com.bean.Car"> 15 <property name="name" value="玛莎拉蒂"/> 16 <property name="color" value="red"/> 17 </bean> 18 19 </beans>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- 使用某个标签之前要导入相应的约束 --> 3 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns="http://www.springframework.org/schema/beans" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xmlns:aop="http://www.springframework.org/schema/aop" 7 xsi:schemaLocation="http://www.springframework.org/schema/beans 8 http://www.springframework.org/schema/beans/spring-beans-4.2.xsd 9 http://www.springframework.org/schema/context 10 http://www.springframework.org/schema/context/spring-context-4.2.xsd 11 http://www.springframework.org/schema/aop 12 http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> 13 14 <!-- 配置目标对象 --> 15 <bean name="userServiceTarget" class="com.service.UserServiceImpl"></bean> 16 <!-- 配置通知对象 --> 17 <bean name="myAdvice" class="com.aspect.MyAdvice"></bean> 18 <!-- 将通知织入目标对象 --> 19 <aop:config> 20 <!-- 配置切入点,即需要加强功能的方法 21 public void com.service.UserServiceImpl.save() 22 void com.service.UserServiceImpl.save() 23 * com.service.UserServiceImpl.save() 24 * com.service.UserServiceImpl.* 25 * com.service.UserServiceImpl.*(..) 26 * com.service.*ServiceImpl.*(..)--> 27 <aop:pointcut id="pc" expression="execution(* com.service.*ServiceImpl.*(..))"/> 28 <aop:aspect ref="myAdvice"> 29 <!-- 将myAdvice的before切入到UserServiceImpl.save() --> 30 <aop:before method="before" pointcut-ref="pc"/> 31 <aop:after-returning method="afterReturning" pointcut-ref="pc"/> 32 <aop:around method="around" pointcut-ref="pc"/> 33 <aop:after-throwing method="afterException" pointcut-ref="pc"/> 34 <aop:after method="after" pointcut-ref="pc"/> 35 </aop:aspect> 36 </aop:config> 37 </beans>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!-- 使用某个标签之前要导入相应的约束 --> 3 <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns="http://www.springframework.org/schema/beans" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xmlns:aop="http://www.springframework.org/schema/aop" 7 xsi:schemaLocation="http://www.springframework.org/schema/beans 8 http://www.springframework.org/schema/beans/spring-beans-4.2.xsd 9 http://www.springframework.org/schema/context 10 http://www.springframework.org/schema/context/spring-context-4.2.xsd 11 http://www.springframework.org/schema/aop 12 http://www.springframework.org/schema/aop/spring-aop-4.2.xsd "> 13 14 <!-- 配置目标对象 --> 15 <bean name="userService" class="com.service.UserServiceImpl"></bean> 16 <!-- 配置通知对象 --> 17 <bean name="myAdvice" class="com.anno.MyAdvice"></bean> 18 <!-- 将通知织入目标对象,利用注解实现 --> 19 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 20 </beans>
相应的实体类与接口
1 package com.bean; 2 3 import org.springframework.beans.factory.annotation.Value; 4 import org.springframework.stereotype.Component; 5 6 /** 7 * @author: 肖德子裕 8 * @date: 2018/9/5 23:38 9 * @description: 车bean 10 */ 11 @Component("car") 12 public class Car { 13 @Value("兰博基尼") 14 private String name; 15 @Value("red") 16 private String color; 17 18 public String getName() { 19 return name; 20 } 21 22 public void setName(String name) { 23 this.name = name; 24 } 25 26 public String getColor() { 27 return color; 28 } 29 30 public void setColor(String color) { 31 this.color = color; 32 } 33 34 @Override 35 public String toString() { 36 return "Car{" + 37 "name=‘" + name + ‘\‘‘ + 38 ", color=‘" + color + ‘\‘‘ + 39 ‘}‘; 40 } 41 }
1 package com.bean; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.beans.factory.annotation.Qualifier; 5 import org.springframework.beans.factory.annotation.Value; 6 import org.springframework.context.annotation.Scope; 7 import org.springframework.stereotype.Component; 8 import org.springframework.stereotype.Controller; 9 import org.springframework.stereotype.Repository; 10 import org.springframework.stereotype.Service; 11 12 import javax.annotation.PostConstruct; 13 import javax.annotation.PreDestroy; 14 import javax.annotation.Resource; 15 16 /** 17 * @author: 肖德子裕 18 * @date: 2018/9/5 19:31 19 * @description: 实体bean 20 * 通过注解获取对象 21 * "@Component("user")==<bean name="user" class="com.bean.User"/>" 22 */ 23 @Component("user") 24 //@Service("user")指定为service层 25 //@Controller("user")指定为web层 26 //@Repository("user")指定为dao层 27 //单例还是多例 28 @Scope(scopeName = "singleton") 29 public class User { 30 //通过反射设置值,破坏了封装性 31 @Value("xdzy") 32 private String name; 33 @Value("15") 34 private int age; 35 //自动配置car属性;但是有多个对象时,不知道获取哪个 36 //@Autowired 37 //指定哪个对象 38 //@Qualifier("car2") 39 //手动注解使用哪个car 40 @Resource(name = "car2") 41 private Car car; 42 43 //创建对象前调用 44 @PostConstruct 45 public void init(){ 46 System.out.println("初始化方法"); 47 } 48 49 //对象销毁前调用 50 @PreDestroy 51 public void destroy(){ 52 System.out.println("销毁方法"); 53 } 54 55 public Car getCar() { 56 return car; 57 } 58 59 public void setCar(Car car) { 60 this.car = car; 61 } 62 63 public String getName() { 64 return name; 65 } 66 67 //通过set设置值,推荐使用 68 @Value("xdzy") 69 public void setName(String name) { 70 this.name = name; 71 } 72 73 public int getAge() { 74 return age; 75 } 76 77 public void setAge(int age) { 78 this.age = age; 79 } 80 81 @Override 82 public String toString() { 83 return "User{" + 84 "name=‘" + name + ‘\‘‘ + 85 ", age=" + age + 86 ", car=" + car + 87 ‘}‘; 88 } 89 }
1 package com.service; 2 3 /** 4 * @author: 肖德子裕 5 * @date: 2018/9/6 20:22 6 * @description: 7 */ 8 public class UserServiceImpl implements UserService{ 9 @Override 10 public void save() { 11 System.out.println("增加用户"); 12 } 13 14 @Override 15 public void del() { 16 System.out.println("删除用户"); 17 } 18 19 @Override 20 public void update() { 21 System.out.println("修改用户"); 22 } 23 24 @Override 25 public void find() { 26 System.out.println("查询用户"); 27 } 28 }
1 package com.service; 2 3 /** 4 * @author: 肖德子裕 5 * @date: 2018/9/6 20:21 6 * @description: 7 */ 8 public interface UserService { 9 void save(); 10 void del(); 11 void update(); 12 void find(); 13 }
动态代理
1 package com.service; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 7 /** 8 * @author: 肖德子裕 9 * @date: 2018/9/6 20:25 10 * @description: 动态代理 11 * 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术 12 * 动态代理可对方法进行增强,如增加事务的打开与提交 13 * 个人理解:它是对service实现类里所有的方法进行了增强; 14 * 在不破坏原有结构的情况下,生成动态代理对象,对原有方法进行增强 15 */ 16 public class UserServiceProxyFactory implements InvocationHandler { 17 private UserService us; 18 19 public UserServiceProxyFactory(UserService us) { 20 this.us = us; 21 } 22 23 public UserService getUserServiceProxy(){ 24 //生成动态代理 25 UserService userProxy=(UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(), 26 UserServiceImpl.class.getInterfaces(), 27 this); 28 //返回一个动态代理对象 29 return userProxy; 30 } 31 32 @Override 33 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 34 System.out.println("打开事务"); 35 Object invoke=method.invoke(us,args); 36 System.out.println("提交事务"); 37 return invoke; 38 } 39 }
Cglib代理
1 package com.service; 2 3 import org.springframework.cglib.proxy.Enhancer; 4 import org.springframework.cglib.proxy.MethodInterceptor; 5 import org.springframework.cglib.proxy.MethodProxy; 6 7 import java.lang.reflect.Method; 8 /** 9 * @author: 肖德子裕 10 * @date: 2018/9/6 20:25 11 * @description: cglib代理 12 * 可以对任何类生成代理,对目标对象进行继承代理 13 */ 14 public class UserServiceProxyFactory2 implements MethodInterceptor { 15 public UserService getUserServiceProxy(){ 16 //生成代理对象 17 Enhancer en=new Enhancer(); 18 //对谁进行代理 19 en.setSuperclass(UserServiceImpl.class); 20 //代理要做什么 21 en.setCallback(this); 22 //创建代理对象 23 UserService us=(UserService) en.create(); 24 return us; 25 } 26 27 @Override 28 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { 29 //打开事务 30 System.out.println("打开事务"); 31 //调用原有方法 32 Object returnValue=methodProxy.invokeSuper(o,objects); 33 //提交事务 34 System.out.println("提交事务"); 35 return returnValue; 36 } 37 }
通知类
1 package com.aspect; 2 3 import org.aspectj.lang.ProceedingJoinPoint; 4 /** 5 * @author: 肖德子裕 6 * @date: 2018/9/7 08:23 7 * @description: 通知 8 * 前置通知:目标方法运行之前 9 * 后置通知(如果出现异常不会调用):之后 10 * 环绕通知:之前之后 11 * 异常拦截通知:出现异常调用 12 * 后置通知(无论是否出现异常都会调用):之后 13 */ 14 public class MyAdvice { 15 //前置通知:目标方法运行之前 16 public void before(){ 17 System.out.println("前置通知"); 18 } 19 //后置通知(如果出现异常不会调用):之后 20 public void afterReturning(){ 21 System.out.println("后置通知(如果出现异常不会调用)"); 22 } 23 //环绕通知:之前之后 24 public Object around(ProceedingJoinPoint pjp) throws Throwable{ 25 System.out.println("环绕通知之前部分"); 26 //调用目标方法 27 Object proceed=pjp.proceed(); 28 System.out.println("环绕通知之后部分"); 29 return proceed; 30 } 31 //异常拦截通知:出现异常调用 32 public void afterException(){ 33 System.out.println("出现异常调用"); 34 } 35 //后置通知(无论是否出现异常都会调用):之后 36 public void after(){ 37 System.out.println("后置通知(无论是否出现异常都会调用)"); 38 } 39 }
1 package com.anno; 2 3 import org.aspectj.lang.ProceedingJoinPoint; 4 import org.aspectj.lang.annotation.*; 5 6 /** 7 * @author: 肖德子裕 8 * @date: 2018/9/7 08:23 9 * @description: 利用注解实现通知 10 * "@Aspect:表示该类是一个通知类 11 */ 12 @Aspect 13 public class MyAdvice { 14 //方便管理切入点 15 @Pointcut("execution(* com.service.*ServiceImpl.*(..))") 16 public void pc(){} 17 18 //配置通知,并指定织入到哪去 19 //前置通知:目标方法运行之前 20 @Before("MyAdvice.pc()") 21 public void before(){ 22 System.out.println("前置通知"); 23 } 24 25 //后置通知(如果出现异常不会调用):之后 26 @AfterReturning("execution(* com.service.*ServiceImpl.*(..))") 27 public void afterReturning(){ 28 System.out.println("后置通知(如果出现异常不会调用)"); 29 } 30 31 //环绕通知:之前之后 32 @Around("execution(* com.service.*ServiceImpl.*(..))") 33 public Object around(ProceedingJoinPoint pjp) throws Throwable{ 34 System.out.println("环绕通知之前部分"); 35 //调用目标方法 36 Object proceed=pjp.proceed(); 37 System.out.println("环绕通知之后部分"); 38 return proceed; 39 } 40 41 //异常拦截通知:出现异常调用 42 @AfterThrowing("execution(* com.service.*ServiceImpl.*(..))") 43 public void afterException(){ 44 System.out.println("出现异常调用"); 45 } 46 47 //后置通知(无论是否出现异常都会调用):之后 48 @After("execution(* com.service.*ServiceImpl.*(..))") 49 public void after(){ 50 System.out.println("后置通知(无论是否出现异常都会调用)"); 51 } 52 }
测试类
1 package com.test; 2 3 import com.bean.User; 4 import com.service.UserService; 5 import com.service.UserServiceImpl; 6 import com.service.UserServiceProxyFactory; 7 import com.service.UserServiceProxyFactory2; 8 import org.junit.Test; 9 import org.junit.runner.RunWith; 10 import org.springframework.context.ApplicationContext; 11 import org.springframework.context.support.ClassPathXmlApplicationContext; 12 import org.springframework.test.context.ContextConfiguration; 13 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 14 15 import javax.annotation.Resource; 16 17 /** 18 * @author: 肖德子裕 19 * @date: 2018/9/6 09:32 20 * @description: 测试注解获取对象 21 * "@RunWith:可以帮助我们创建容器,这样xml地址改动,测试方法不用全部修改 22 * "@ContextConfiguration:指定容器位置 23 * 注意junit版本问题 24 */ 25 //@RunWith(SpringJUnit4ClassRunner.class) 26 //@ContextConfiguration("classpath:resources/applicationContext.xml") 27 public class Demo1 { 28 // @Resource(name = "user") 29 // private User user; 30 // 31 // @Test 32 // public void test(){ 33 // System.out.println(user); 34 // } 35 36 //动态代理 37 @Test 38 public void test1(){ 39 UserService us=new UserServiceImpl(); 40 UserServiceProxyFactory factory=new UserServiceProxyFactory(us); 41 UserService userProxy=factory.getUserServiceProxy(); 42 userProxy.save(); 43 44 //代理对象和被代理对象实现了相同的接口(false) 45 System.out.println(userProxy instanceof UserServiceImpl); 46 } 47 48 //cglib代理 49 @Test 50 public void test2(){ 51 UserServiceProxyFactory2 factory=new UserServiceProxyFactory2(); 52 UserService userProxy=factory.getUserServiceProxy(); 53 userProxy.save(); 54 55 //代理对象继承了被代理对象(true) 56 System.out.println(userProxy instanceof UserServiceImpl); 57 } 58 59 //通知织入 60 @Test 61 public void test(){ 62 //创建容器对象 63 ApplicationContext ac=new ClassPathXmlApplicationContext("com/aop/applicationContext.xml"); 64 //获取user对象 65 UserService userService=(UserService) ac.getBean("userServiceTarget"); 66 userService.save(); 67 } 68 69 //注解通知织入 70 @Test 71 public void test4(){ 72 //创建容器对象 73 ApplicationContext ac=new ClassPathXmlApplicationContext("com/anno/applicationContext.xml"); 74 //获取user对象 75 UserService userService=(UserService) ac.getBean("userService"); 76 userService.save(); 77 } 78 }
标签:win expr isp package creat == 通过 容器 初始
原文地址:https://www.cnblogs.com/xdzy/p/9603630.html