码迷,mamicode.com
首页 > 编程语言 > 详细

Spring框架基础2

时间:2018-09-07 13:56:44      阅读:130      评论:0      收藏:0      [点我收藏+]

标签: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 }
Car
技术分享图片
 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 }
User
技术分享图片
 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 }
UserServiceImpl
技术分享图片
 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 }
UserService

动态代理

技术分享图片
 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 }
UserServiceProxyFactory

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 }
UserServiceProxyFactory2

通知类

技术分享图片
 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 }
MyAdvice
技术分享图片
 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 }
MyAdvice 注解版

测试类

技术分享图片
 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 }
test

 

Spring框架基础2

标签:win   expr   isp   package   creat   ==   通过   容器   初始   

原文地址:https://www.cnblogs.com/xdzy/p/9603630.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!