Spring 入门

简单工厂

实例:学生学习课程

创建课程工厂、课程接口

1
2
3
4
5
6
package top.eshyee.newinstance;
//课程接口
public interface ICourse {

public void learn() ;
}
1
2
3
4
5
6
7
8
package top.eshyee.newinstance;

public class JavaCourse implements ICourse{
@Override
public void learn() {
System.out.println("java课程");
}
}
1
2
3
4
5
6
7
8
9
package top.eshyee.newinstance;

public class HtmlCourse implements ICourse{

@Override
public void learn() {
System.out.println("html课程");
}
}

课程工厂

1
2
3
4
5
6
7
8
9
10
11
package top.shyee.factory;
import top.eshyee.newinstance.HtmlCourse;
import top.eshyee.newinstance.ICourse;
import top.eshyee.newinstance.JavaCourse;

public class CourseFactory {
public static ICourse getCourse(String name) {
return name.equals("java") ? new JavaCourse() : name.equals("html")?new HtmlCourse():null;
}
}

学生类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package top.eshyee.entity;

import top.eshyee.newinstance.HtmlCourse;
import top.eshyee.newinstance.ICourse;
import top.eshyee.newinstance.JavaCourse;
import top.shyee.factory.CourseFactory;

public class Student {
private int stuNo;
private String stuName;
private int stuAge;

public int getStuNo() {
return stuNo;
}

public void setStuNo(int stuNo) {
this.stuNo = stuNo;
}

public String getStuName() {
return stuName;
}

public void setStuName(String stuName) {
this.stuName = stuName;
}

public int getStuAge() {
return stuAge;
}

public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}

@Override
public String toString() {
return "Student [stuNo=" + stuNo + ", stuName=" + stuName + ", stuAge=" + stuAge + "]";
}

// 学生学习课程
public void learn(String name) {
ICourse course1=CourseFactory.getCourse(name);
course1.learn();
}
}

测试

public class Test1 {
public static void main(String[] args) {
StudentlearnwithFactory();
}

1
2
3
4
5
6
7
8
public class Test1 {
public static void main(String[] args) {
StudentlearnwithFactory();
}
public static void StudentlearnwithFactory() {
Student student = new Student();
student.learn("java");
}}

测试结果:java课程

IOC

超级工厂,可以放各种对象。控制反转,也成为DI(依赖注入)

使用IOC实现以上操作

配置XML–添加三个bean

1
2
3
4
5
6
7
<bean id="student" class="top.eshyee.entity.Student">
<property name="stuNo" value="1"></property>
<property name="stuAge" value="2"></property>
<property name="stuName" value="genge"></property>
</bean>
<bean id="JavaCourse" class="top.eshyee.newinstance.JavaCourse"></bean>
<bean id="HtmlCourse" class="top.eshyee.newinstance.HtmlCourse"></bean>

重写学生的learn方法

1
2
3
4
5
public void learn(String name) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ICourse course =(ICourse)context.getBean(name);
course.learn();
}

写个测试方法

1
2
3
4
5
public static void StudentlearnwithIOC() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = (Student) context.getBean("student");
student.learn("JavaCourse");
}

运行结果:java课程

依赖注入(DI)

set注入

property

创建teacher和course类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package top.eshyee.entity;

public class Teacher {
private String name;
private int age;
public String getName() {
return name;
}
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 "Teacher [name=" + name + ", age=" + age + "]";
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package top.eshyee.entity;

public class Course {
private String courseName;
private int courseHour;
private Teacher teacher;//依赖于teacher
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public int getCourseHour() {
return courseHour;
}
public void setCourseHour(int courseHour) {
this.courseHour = courseHour;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
@Override
public String toString() {
return "Course [courseName=" + courseName + ", courseHour=" + courseHour + ", teacher=" + teacher + "]";
}
}

加入到IOC中

1
2
3
4
5
6
7
8
9
<bean id="teacher" class="top.eshyee.entity.Teacher">
<property name="name" value="Shyee"></property>
<property name="age" value="12"></property>
</bean>
<bean id="course" class="top.eshyee.entity.Course">
<property name="courseName" value="JAVA"></property>
<property name="courseHour" value="13"></property>
<property name="teacher" ref="teacher"></property>
</bean>

写一个测试类

1
2
3
4
5
6
public static void testDI() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Teacher teacher = (Teacher) context.getBean("teacher");
Course course = (Course) context.getBean("course");
System.out.println(course);
}

运行结果:Course [courseName=JAVA, courseHour=13, teacher=Teacher [name=Shyee, age=12]]

赋值默认是set方法

构造方法注入

constructor

修改xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<bean id="teacher" class="top.eshyee.entity.Teacher">
<!-- index 指定参数位置
<constructor-arg value="Shyeee" index="0"></constructor-arg>
<constructor-arg value="15" index="1"></constructor-arg> -->
<!-- name指定参数
<constructor-arg value="Shyeee" name="name"></constructor-arg>
<constructor-arg value="15" name="age"></constructor-arg> -->
<!-- 指定类型
<constructor-arg value="Shyeee" type="String"></constructor-arg>
<constructor-arg value="15" type="int"></constructor-arg>-->
<!-- 默认 -->
<constructor-arg value="Shyeee" ></constructor-arg>
<constructor-arg value="15" ></constructor-arg>
</bean>
<bean id="course" class="top.eshyee.entity.Course">
<constructor-arg value="PYTHON"></constructor-arg>
<constructor-arg value="15"></constructor-arg>
<constructor-arg ref="teacher"></constructor-arg>
</bean>

加入构造方法

Course

1
2
3
4
5
6
7
8
9
public Course(String courseName, int courseHour, Teacher teacher) {
super();
this.courseName = courseName;
this.courseHour = courseHour;
this.teacher = teacher;
}
public Course() {
super();
}

Teacher

1
2
3
4
5
6
7
8
9
public Teacher(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Teacher() {
super();
}

运行结果:Course [courseName=PYTHON, courseHour=15, teacher=Teacher [name=Shyeee, age=15]]

P命名空间

xmlns:p="http://www.springframework.org/schema/p"

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="teacher" class="top.eshyee.entity.Teacher" p:name="Shyeeee" p:age="14"></bean>
<bean id="course" class="top.eshyee.entity.Course" p:courseName="ORACLE" p:courseHour="1" p:teacher-ref="teacher">
</bean></beans>

运行结果:Course [courseName=ORACLE, courseHour=1, teacher=Teacher [name=Shyeeee, age=14]]

各种类型的注入

Arrays&List&Map&Properties&Set

创建包含各种类型的类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package top.eshyee.entity;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public class AllcollectionType {
private List<String> list;
private String[] array;
private Set<String> set;
private Map<String, String> map;
private Properties properties;
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
public String[] getArray() {
return array;
}
public void setArray(String[] array) {
this.array = array;
}
public Set<String> getSet() {
return set;
}
public void setSet(Set<String> set) {
this.set = set;
}
public Map<String, String> getMap() {
return map;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
String ss="";
for(String s:array) {
ss=ss+s+",";
}
ss="["+ss+"]";
return "AllcollectionType [list=" + list + "\n array=" + ss + "\n set=" + set + "\n map=" + map
+ "\n properties=" + properties + "]";
}
}

注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<bean id="collectionType"
class="top.eshyee.entity.AllcollectionType">
<property name="array">
<array>
<value>I</value>
<value>A</value>
<value>M</value>
</array>
</property>
<property name="list">
<list>
<value>S</value>
<value>H</value>
<value>Y</value>
<value>E</value>
<value>E</value>
</list>
</property>
<property name="map">
<map>
<entry>
<key>
<value>NI</value>
</key>
<value>ni</value>
</entry>
<entry>
<key>
<value>C</value>
</key>
<value>c</value>
</entry>
<entry>
<key>
<value>E</value>
</key>
<value>e</value>
</entry>
</map>
</property>
<property name="properties">
<props>
<prop key="TO">to</prop>
<prop key="ME">me</prop>
<prop key="ET">et</prop>
</props>
</property>
<property name="set">
<set>
<value>Y</value>
<value>O</value>
<value>U</value>
</set>
</property>
</bean>

set和array都可以用list标签,相反也可,但是建议用相应标签

测试

1
2
3
4
5
public static void testcollectionType() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AllcollectionType a = (AllcollectionType) context.getBean("collectionType");
System.out.println(a);
}

运行结果

AllcollectionType [list=[S, H, Y, E, E]
array=[I,A,M,]
set=[Y, O, U]
map={NI=ni, C=c, E=e}
properties={ME=me, TO=to, ET=et}]

null和空字符串

1
2
3
4
5
6
7
8
9
10
11
<bean id="student1" class="top.eshyee.entity.Student">
<!-- 赋空值 -->
<property name="stuNo">
<!-- null -->
<null />
</property>
<!-- 空字符串"" -->
<property name="stuName">
<value></value>
</property>
</bean>

自动装配

autowire="byName"会自动找一个id为teacher 的bean,只有对象之间的依赖关系可以自动装配

1
2
3
4
5
6
7
8
9
<bean id="teacher" class="top.eshyee.entity.Teacher">
<property name="name" value="Shyee"></property>
<property name="age" value="12"></property>
</bean>
<bean id="course" class="top.eshyee.entity.Course"
autowire="byName">
<property name="courseName" value="JAVA"></property>
<property name="courseHour" value="13"></property>
</bean>

运行结果:Course [courseName=JAVA, courseHour=13, teacher=Teacher [name=Shyee, age=12]]

autowire="byType"按类型自动装配,寻找一个teacher类型的bean,但是有两个teacher会报错。

expected single matching bean but found 2: teacher1,teacher2

autowire="constructor"适用于构造方法中有多个依赖

添加全局的autowire–default-autowire="byName"

1
2
3
4
5
6
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName"
>

注解

配置扫描器

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<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"
default-autowire="byName"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
<!-- 配置扫描器 -->
<context:component-scan base-package="top.eshyee.dao"></context:component-scan></beans>

用注解声明一个bean

相当于在xml中的<bean id="stuentDao" class="top.eshyee.dao.StuentDaoImpl"></bean>

1
2
3
4
5
6
7
8
9
10
package top.eshyee.dao;
import org.springframework.stereotype.Component;
import top.eshyee.entity.Student;
@Component("StuentDao")
public class StuentDaoImpl {
public void addStudent(Student student) {
// TODO Auto-generated method stub
System.out.println("增加学生");
}
}

dao层注解:@Repository

service层注解:@Service

控制器层注解:@Controller

使用注解实现事务

需要使用到spring-tx-4.3.9.RELEASE.jarojdbc.jarcommons-dbcp.jarcommons-pool.jarspring-jdbc-4.3.9.RELEASE.jaraopalliance.jar

配置xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 配置数据库相关-事务 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver"></property>
<property name="url" value="127.0.0.1:1521:ORCL"></property>
<property name="username" value="SCOTT"></property>
<property name="password" value="tiger"></property>
<property name="maxActive" value="10"></property>
<property name="maxIdle" value="6"></property>
</bean>
<!-- 配置事务管理器-txmanager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 增加对事务的支持 -->
<tx:annotation-driven transaction-manager="txManager"/>

创建DAO层及实现类

1
2
3
4
5
6
7
package top.eshyee.dao;

import top.eshyee.entity.Student;

public interface IStudentDao {
public void addStudent(Student student);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package top.eshyee.dao.impl;
import org.springframework.stereotype.Repository;

import top.eshyee.dao.IStudentDao;
import top.eshyee.entity.Student;
//相当于<bean id="stuentDao" class="top.eshyee.dao.StuentDaoImpl"></bean>
@Repository("StuentDao")
public class StudentDaoImpl implements IStudentDao{
public void addStudent(Student student) {
// TODO Auto-generated method stub
System.out.println("增加学生");
}
}

创建service层及实现类

1
2
3
4
5
6
7
package top.eshyee.service;

import top.eshyee.entity.Student;

public interface IStudentService {
void addStudent(Student student);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package top.eshyee.service.impl;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import top.eshyee.dao.IStudentDao;
import top.eshyee.entity.Student;
import top.eshyee.service.IStudentService;

public class StudentServiceImpl implements IStudentService {
IStudentDao studentDao ;

@Transactional(readOnly = false ,propagation = Propagation.REQUIRED)
@Override
public void addStudent(Student student) {
studentDao.addStudent(student);
}
public IStudentDao getStudentDao() {
return studentDao;
}
public void setStudentDao(IStudentDao studentDao) {
this.studentDao = studentDao;
}
}

注入到IOC

1
2
3
4
5
<bean id="studentDao" class="top.eshyee.dao.impl.StudentDaoImpl"></bean>
<bean id="studentService"
class="top.eshyee.service.impl.StudentServiceImpl">
<property name="studentDao" ref="studentDao"></property>
</bean>

AOP

面向方面编程

前置通知

每当执行add之前自动执行的方法

准备jar

aopalliance.jaraspectjweaver-1.5.3.jar

编写前置通知

1
2
3
4
5
6
7
8
9
10
package top.eshyee.aop;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class LogBefore implements MethodBeforeAdvice{
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
// TODO Auto-generated method stub
System.out.println("前置通知");
}
}

配置前置通知

1
2
3
4
5
6
7
8
<!-- 配置前置通知 -->
<bean id="logBefore" class="top.eshyee.aop.LogBefore"></bean>

<!-- 将addstudent方法与通知进行关联 -->
<aop:config>
<aop:pointcut expression="execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student))" id="pointcut"/>
<aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
</aop:config>

测试

1
2
3
4
5
public static void testAOP() {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
IStudentService studentService= (IStudentService) context.getBean("studentService");
Student student=getStudent1();
studentService.addStudent(student);

运行结果:

前置通知
增加学生

expression=“execution(…)” 的常见写法

举例 含义
public boolean addStudent(org.lanqiao.entity.Student)) 所有返回类型为boolean、参数类型为org.lanqiao.entity.Student的addStudent()方法。
public boolean org.lanqiao.service.IStudentService. addStudent(org.lanqiao.entity.Student) org.lanqiao.service.IStudentService类(或接口)中的addStudent()方法,并且返回类型是boolean、参数类型是org.lanqiao.entity.Student
public * addStudent(org.lanqiao.entity.Student) “*”代表任意返回类型
public void *( org.lanqiao.entity.Student) “*”代表任意方法名
public void addStudent(..) “..”代表任意参数列表
* org.lanqiao.service..(..) org.lanqiao.service.IStudentService包中,包含的所有方法(不包含子包中的方法)
* org.lanqiao.service...(..) org.lanqiao.service.IStudentService包中,包含的所有方法(包含子包中的方法)

后置通知

service层添加一个新业务 void deleteStudentByno(int stuNo);

添加实现方法

1
2
3
4
@Override
public void deleteStudentByno(int stuNo) {
System.out.println("删除学生");
}

编写AOP

1
2
3
4
5
6
7
8
9
package top.eshyee.aop;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
public class LogAfter implements AfterReturningAdvice{
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("后置通知,目标对象:"+target+",调用的方法名:"+method.getName()+",调用的参数个数:"+args.length+",方法的返回值:"+returnValue);
}
}

注入IOC

1
2
3
4
5
6
7
8
<!-- 配置后置通知 -->
<bean id="logAfter" class="top.eshyee.aop.LogAfter"></bean>
<!-- 将addstudent方法与通知进行关联 -->
<aop:config>
<aop:pointcut expression="execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student)) or execution(public void top.eshyee.service.impl.StudentServiceImpl.deleteStudentByno(int))" id="pointcut"/>
<aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAfter" pointcut-ref="pointcut"/>
</aop:config>

运行结果:

前置通知
增加学生
后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@5b1ebf56,调用的方法名:addStudent,调用的参数个数:1,方法的返回值:null
前置通知
删除学生
后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@5b1ebf56,调用的方法名:deleteStudentByno,调用的参数个数:1,方法的返回值:null

异常通知

源码注释中:Implementing classes must implement methods of the form: void afterThrowing([Method, args, target], ThrowableSubclass);

及必须实现以上方法

编写AOP

1
2
3
4
5
6
7
8
9
package top.eshyee.aop;
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;

public class LogException implements ThrowsAdvice{
public void afterThrowing(Method method, Object[] args,Object target, Throwable ex) {
System.out.println("异常通知,目标对象:"+target+",调用方法:"+method.getName()+",参数个数:"+args.length+",异常原因:"+ex.getMessage());
}
}

注入IOC

1
2
3
4
5
6
7
8
9
<!-- 配置异常通知 -->
<bean id="logException" class="top.eshyee.aop.LogException"></bean>
<!-- 将addstudent方法与通知进行关联 -->
<aop:config>
<aop:pointcut expression="execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student)) or execution(public void top.eshyee.service.impl.StudentServiceImpl.deleteStudentByno(int))" id="pointcut"/>
<aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAfter" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logException" pointcut-ref="pointcut"/>
</aop:config>

搞点异常

1
2
3
4
5
@Override
public void deleteStudentByno(int stuNo) {
int a=1/0;
System.out.println("删除学生");
}

运行结果:

前置通知
增加学生
后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@16414e40,调用的方法名:addStudent,调用的参数个数:1,方法的返回值:null
前置通知
异常通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@16414e40,调用方法:deleteStudentByno,参数个数:1,异常原因:/ by zero
Exception in thread "main" java.lang.ArithmeticException: / by zero

环绕通知

前后+异常

编写AOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package top.eshyee.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class LogAround implements MethodInterceptor {

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object result = null;
try {
System.out.println("环绕通知实现的前置通知");
result = invocation.proceed();
// result就是目标方法如add student的返回值
System.out.println("环绕通知实现的后置通知,目标对象:" + invocation.getThis() + ",调用的方法名:"
+ invocation.getMethod().getName() + ",调用的参数个数:" + invocation.getArguments() + ",方法的返回值:" + result);

} catch (Exception e) {
System.out.println("环绕通知实现的异常通知");
}
return result;
}
}

注入IOC

1
2
3
4
5
6
7
8
9
10
<!-- 配置环绕通知 -->
<bean id="logAround" class="top.eshyee.aop.LogAround"></bean>
<!-- 将addstudent方法与通知进行关联 -->
<aop:config>
<aop:pointcut expression="execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student)) or execution(public void top.eshyee.service.impl.StudentServiceImpl.deleteStudentByno(int))" id="pointcut"/>
<aop:advisor advice-ref="logBefore" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAfter" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logException" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="logAround" pointcut-ref="pointcut"/>
</aop:config>

运行结果:

前置通知
环绕通知实现的前置通知
增加学生
环绕通知实现的后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@46dffdc3,调用的方法名:addStudent,调用的参数个数:[Ljava.lang.Object;@5a709816,方法的返回值:null
后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@46dffdc3,调用的方法名:addStudent,调用的参数个数:1,方法的返回值:null
前置通知
环绕通知实现的前置通知
删除学生
环绕通知实现的后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@46dffdc3,调用的方法名:deleteStudentByno,调用的参数个数:[Ljava.lang.Object;@78383390,方法的返回值:null
后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@46dffdc3,调用的方法名:deleteStudentByno,调用的参数个数:1,方法的返回值:null

使用注解实现AOP

在XML配置扫描器以及对AOP的支持

1
2
3
4
<!-- 开启注解对AOP的支持 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 开启扫描器对该包的扫描 -->
<context:component-scan base-package="top.eshyee.aop"></context:component-scan>

编写AOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package top.eshyee.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Component("logAnnotation")
@Aspect
public class LogWithAnnotation {
@Before("execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student))")
public void myBefore(JoinPoint jp) {
System.out.println("注解形式--前置通知");
}

@AfterReturning(pointcut = "execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student))", returning = "returningValue")
public void myAfterReturning(JoinPoint jp, Object returningValue) {
System.out.println("注解形式--后置通知,目标对象:" + jp.getTarget() + ",方法名:" + jp.getSignature() + ",参数列表:"
+ Arrays.toString(jp.getArgs()) + "返回值:" + returningValue);
}

@AfterThrowing(pointcut="execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student))",throwing ="e")
public void myException(JoinPoint jp,NullPointerException e) {//通过第二个参数来捕获特定异常如NullPointerException
System.out.println("注解形式--异常通知");
}

@Around("execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student))")
public void myAround(ProceedingJoinPoint pjp) {
try {
System.out.println("注解形式--环绕通知--前置通知");
pjp.proceed();
System.out.println("注解形式--环绕通知--后置通知");
} catch (Throwable e) {
System.out.println("注解形式--环绕通知--异常通知");
} finally {
System.out.println("注解形式--环绕通知--最终通知");
}
}
@After("execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student))")
public void myAfter() {
System.out.println("注解形式--最终通知");
}
}

运行结果:

注解形式–环绕通知–前置通知
注解形式–前置通知
增加学生
注解形式–环绕通知–后置通知
注解形式–环绕通知–最终通知
注解形式–最终通知
注解形式–后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@77b14724,方法名:void top.eshyee.service.IStudentService.addStudent(Student),参数列表:[Student [stuNo=0, stuName=genge, stuAge=0]]返回值:null
删除学生

基于SCHEMA配置

类似于实现接口的方式

编写AOP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package top.eshyee.aop;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class LogSchema {

public void afterReturning(JoinPoint jp,Object returningValue) throws Throwable {
System.out.println("Schema形式--后置通知,目标对象:" + jp.getTarget() + ",方法名:" + jp.getSignature() + ",参数列表:"
+ Arrays.toString(jp.getArgs()) + "返回值:" + returningValue);
}
public void before() throws Throwable {
System.out.println("Schema后置通知");

}
public void myException(JoinPoint jp) {
System.out.println("Schema异常通知");
}
public Object myAround(ProceedingJoinPoint pjp) {
Object result=null;
try {
System.out.println("Schema环绕前置通知");
result=pjp.proceed();
System.out.println("Schema环绕后置通知");
} catch (Throwable e) {
System.out.println("Schema环绕异常通知");
}
return result;//返回目标方法的返回值
}
}

注入IOC

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 将准备转入通知 的类纳入IOC -->
<bean id="logSchema" class="top.eshyee.aop.LogSchema"></bean>

<!-- 将addstudent方法与通知进行关联 -->
<aop:config>
<aop:pointcut expression="execution(public void top.eshyee.service.impl.StudentServiceImpl.addStudent(top.eshyee.entity.Student)) or execution(public void top.eshyee.service.impl.StudentServiceImpl.deleteStudentByno(int))" id="pointcut2"/>
<aop:aspect ref="logSchema" >
<aop:before method="before" pointcut-ref="pointcut2"/>
<aop:after-returning method="afterReturning" returning="returningValue" pointcut-ref="pointcut2"/>
<aop:after-throwing method="myException" pointcut-ref="pointcut2"/>
<aop:around method="myAround" pointcut-ref="pointcut2"/>
</aop:aspect>
</aop:config>

运行结果:

Schema后置通知
Schema环绕前置通知
注解形式–环绕通知–前置通知
注解形式–前置通知
增加学生
注解形式–后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@31000e60,方法名:void top.eshyee.service.IStudentService.addStudent(Student),参数列表:[Student [stuNo=0, stuName=genge, stuAge=0]]返回值:null
注解形式–最终通知
注解形式–环绕通知–后置通知
注解形式–环绕通知–最终通知
Schema环绕后置通知
Schema形式–后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@31000e60,方法名:void top.eshyee.service.IStudentService.addStudent(Student),参数列表:[Student [stuNo=0, stuName=genge, stuAge=0]]返回值:null
Schema后置通知
Schema环绕前置通知
删除学生
Schema环绕后置通知
Schema形式–后置通知,目标对象:top.eshyee.service.impl.StudentServiceImpl@31000e60,方法名:void top.eshyee.service.IStudentService.deleteStudentByno(int),参数列表:[1]返回值:null