IOC和AOP扩展

Posted pere

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IOC和AOP扩展相关的知识,希望对你有一定的参考价值。

L120201X1

构造注入,在L120108X1的项目上做出以下改变

1、改变UserServiceImpl.java成以下内容

package service.impl;

import dao.UserDao;

import entity.User;

import service.UserService;

//用户业务类,实现对User功能的业务管理

public class UserServiceImpl implements UserService {

//声明接口类型的引用,和具体实现类解耦合

private UserDao dao;

//dao 属性的setter访问器,会被Spring调用,实现设值注入

/*public void setDao(UserDao dao) {

this.dao=dao; }*/

public UserServiceImpl(UserDao dao) {

this.dao = dao;}

public UserServiceImpl() {}

public void addNewUser(User user) {

//调用用户DAO的方法保存用户信息

dao.save(user);}}

2、改变ApplicationContext.xml成以下内容

<?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:aop="http://www.springframework.org/schema/aop"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>

<bean id="userService" class="service.impl.UserServiceImpl">

<constructor-arg>

<ref bean="userDao"/>

</constructor-arg></bean></beans>

3、运行AopTest.java得出以下结果:

保存用户信息到数据库

L120201X2

构造注入赋值顺序测试

1、在UserServiceImpl.java中增加以下内容

public UserServiceImpl(UserDao dao,String s1) {

this.dao = dao;

this.s1=s1;

}

public UserServiceImpl(String s2,UserDao dao) {

this.dao = dao;

this.s2=s2;

}

public void addNewUser(User user) {

dao.save(user);

System.out.println("s1="+s1);

System.out.println("s2="+s2);}}

2、ApplicationContext.xml增加以下内容

<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>

<bean id="userService" class="service.impl.UserServiceImpl">

<!-- 通过constructor-arg元素为构造方法里面的参数赋值 -->

<constructor-arg>

<ref bean="userDao"/>

</constructor-arg>

<constructor-arg>

<value>123</value>

</constructor-arg>

</bean>

3、运行AopTest.java得出以下结果:

保存用户信息到数据库

s1=null

s2=123

4、如果将

<constructor-arg>

<value>123</value>

</constructor-arg>

改成

<constructor-arg index="1">

<value>123</value>

</constructor-arg>

运行结果为:

保存用户信息到数据库

s1=123

s2=null

5、如果将上面的

<constructor-arg index="1">

<value>123</value>

</constructor-arg>

改成

<constructor-arg type="int">

<value>123</value>

</constructor-arg>

以及在UserServiceImpl.java中增加以下代码

private int i1;

public UserServiceImpl(UserDao dao,int i1) {

this.dao = dao;

this.i1=i1;

}

System.out.println("i1="+i1);

运行结果为

保存用户信息到数据库

s1=null

i1=123

L120202X1

1、将L120201X2中user的email变量改成age变量,同时增加其getter和setter方法

private String age;// 年龄

public String getAge() {

return age;

}

public void setAge(String age) {

this.age = age;

}

2、在UserDaoImpl的save方法中增加以下代码

System.out.println("已配置的用户信息如下:");

System.out.println(" 用户名为:"+user.getUsername());

System.out.println(" 年龄为:"+user.getAge());

System.out.println(" 邮箱为:"+user.getEmail());

3、UserServiceImpl中代码

package service.impl;

import dao.UserDao;

import entity.User;

import service.UserService;

public class UserServiceImpl implements UserService {

private UserDao dao;

public UserDao getDao() {

return dao;

}

public void setDao(UserDao dao) {

this.dao = dao;

}

public void addNewUser(User user) {

dao.save(user);

}

}

4、ApplicationContext.xml增加以下内容

头部增加xmlns:p="http://www.springframework.org/schema/p"

配置为

<bean id="user" class="entity.User" p:username="张三" p:age="20" p:email="test@123.com"></bean>

<bean id="userDao" class="dao.impl.UserDaoImpl" ></bean>

<bean id="userService" class="service.impl.UserServiceImpl" p:dao-ref="userDao">

</bean>

5、test类中代码

ApplicationContext context=new ClassPathXmlApplicationContext("ApplicationContext.xml");

UserService userService=(UserService)context.getBean("userService");

User user=(User)context.getBean("user");

userService.addNewUser(user);

5、运行结果

保存用户信息到数据库

已配置的用户信息如下:

用户名为:张三

年龄为:20

邮箱为:test@123.com

L120203X1

不同数据类型注入

技术图片

1、user类代码

package entity;

/**

* 用户实体类

*/

public class User implements java.io.Serializable {

private String username; // 用户名

// getter & setter

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

}

2、TestEntity代码

package entity;

import java.util.List;

import java.util.Map;

import java.util.Properties;

import java.util.Set;

public class TestEntity {

private String specialCharacter1; // 特殊字符值1

private String specialCharacter2; // 特殊字符值2

private User innerBean; // JavaBean类型

private List<String> list; // List类型

private String[] array; // 数组类型

private Set<String> set; // Set类型

private Map<String, String> map; // Map类型

private Properties props; // Properties类型

private String emptyValue; // 注入空字符串值

private String nullValue = "init value"; // 注入null值

public void setSpecialCharacter1(String specialCharacter1) {

this.specialCharacter1 = specialCharacter1;

}

public void setSpecialCharacter2(String specialCharacter2) {

this.specialCharacter2 = specialCharacter2;

}

public void setInnerBean(User user) {

this.innerBean = user;

}

public void setList(List<String> list) {

this.list = list;

}

public void setArray(String[] array) {

this.array = array;

}

public void setSet(Set<String> set) {

this.set = set;

}

public void setMap(Map<String, String> map) {

this.map = map;

}

public void setProps(Properties props) {

this.props = props;

}

public void setEmptyValue(String emptyValue) {

this.emptyValue = emptyValue;

}

public void setNullValue(String nullValue) {

this.nullValue = nullValue;

}

public void showValue() {

System.out.println("特殊字符1:" + this.specialCharacter1);

System.out.println("特殊字符2:" + this.specialCharacter2);

System.out.println("内部Bean:" + this.innerBean.getUsername());

System.out.println("List属性:" + this.list);

System.out.println("数组属性[0]:" + this.array[0]);

System.out.println("Set属性:" + this.set);

System.out.println("Map属性:" + this.map);

System.out.println("Properties属性:" + this.props);

System.out.println("注入空字符串:[" + this.emptyValue + "]");

System.out.println("注入null值:" + this.nullValue);

}

}

3、test类代码

package test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import entity.TestEntity;

public class Test {

@org.junit.Test

public void test() {

// 使用ApplicationContext接口的实现类ClassPathXmlApplicationContext加载Spring配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext(

"applicationContext.xml");

TestEntity entity = (TestEntity) ctx.getBean("testEntity");

entity.showValue();

}}

4、applicationContext.xml代码

<?xml version="1.0" encoding="UTF-8"?>

<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-3.2.xsd">

<bean id="testEntity" class="entity.TestEntity">

<!-- 使用CDATA处理xml中特殊字符 -->

<property name="specialCharacter1">

<value><![CDATA[P&G]]></value>

</property>

<!-- 使用CDATA处理xml中特殊字符 -->

<property name="specialCharacter2">

<value>P&G</value>

</property>

<property name="innerBean">

<bean class="entity.User">

<property name="username">

<value>张三</value>

</property>

</bean>

</property>

<!-- 配置list集合类型的值 -->

<property name="list">

<list>

<value>足球</value>

<value>篮球</value>

</list>

</property>

<!-- 配置array的值 -->

<property name="array">

<list>

<value>足球</value>

<value>篮球</value>

</list>

</property>

<!-- 配置set集合类型的值 -->

<property name="set">

<list>

<value>足球</value>

<value>篮球</value>

</list>

</property>

<!-- 配置map集合类型的值 -->

<property name="map">

<map>

<entry>

<key><value>football</value></key>

<value>足球</value>

</entry>

<entry>

<key><value>basketball</value></key>

<value>篮球</value>

</entry>

</map>

</property>

<property name="props">

<props>

<prop key="football">足球</prop>

<prop key="basketball">篮球</prop>

</props>

</property>

<property name="emptyValue">

<value></value>

</property>

<property name="nullValue">

<null/>

</property>

</bean>

</beans>

5、运行结果

特殊字符1:P&G

特殊字符2:P&G

内部Bean:张三

List属性:[足球, 篮球]

数组属性[0]:足球

Set属性:[足球, 篮球]

Map属性:{football=足球, basketball=篮球}

Properties属性:{football=足球, basketball=篮球}

注入空字符串:[]

注入null值:null

L120204X1

异常抛出增强,在L120108X1的项目上做出以下改变

1、将UserSercviceLogger.java名字改为ErrorLogger.java

里面的方法为:

public void afterThrowing(JoinPoint jp,RuntimeException e){

log.error(jp.getSignature().getName()+"方法发成异常"+e);}

2、UserDaoImpl.java中的save方法改为

public void save(User user) {

System.out.println("保存用户信息到数据库");

throw new RuntimeException("为测试程序运行效果抛出的异常"); }

3、ApplicationContext.xml的配置为

<bean id="userDao" class="dao.impl.UserDaoImpl"></bean>

<bean id="userService" class="service.impl.UserServiceImpl">

<property name="dao" ref="userDao"/>

</bean>

<!-- 声明增强类的bean元素 -->

<bean id="errorLogger" class="aop.ErrorLogger"></bean>

<!-- <aop:config>是最外层标签,所有的aop配置都需在里面进行  -->

<aop:config>

<!-- 切入点,id为名字可以随便取,但上下文一致,expression为表达式-->

<aop:pointcut id="pointcut" expression=

"execution(public void addNewUser(entity.User))"/>

<!--after-throwing方法定义为异常抛出增强,并引入切入点pointcut,通过throwing属性为参数e注入异常实例-->

<aop:aspect ref="errorLogger">

<!-- 设置后置增强,引入切入点,注入目标方法的返回值result-->

<aop:after-throwing method="afterThrowing"

pointcut-ref="pointcut" throwing="e"/>

</aop:aspect>

</aop:config>

3、运行结果为

保存用户信息到数据库‘

[ERROR] 2019-10-25 20:36:16,250 aop.ErrorLogger - addNewUser方法发成异常java.lang.RuntimeException: 为测试程序运行效果抛出的异常

L120204X2

最终增强,在L120204X1基础上修改代码

1、将ErrorLogger.java名字改为AfterLogger.java

里面的方法为

public void afterLogger(JoinPoint jp) {

log.info(jp.getSignature().getName() + " 方法结束执行。"); }

2、applicationContext.xml中的配置为

<bean id="dao" class="dao.impl.UserDaoImpl"></bean>

<bean id="service" class="service.impl.UserServiceImpl">

<property name="dao" ref="dao"></property>

</bean>

<!-- 声明增强方法所在的Bean -->

<bean id="theLogger" class="aop.AfterLogger"></bean>

<!-- 配置切面 -->

<aop:config>

<!-- 定义切入点 -->

<aop:pointcut id="pointcut" expression="execution(* service.UserService.*(..))" />

<!-- 引用包含增强方法的Bean -->

<aop:aspect ref="theLogger">

<!-- 将afterLogger()方法定义为最终增强并引用pointcut切入点 -->

<aop:after method="afterLogger" pointcut-ref="pointcut"/>

</aop:aspect>

</aop:config>

运行结果为

保存用户信息到数据库

10-25 21:20:18[INFO]aop.AfterLogger

-addNewUser 方法结束执行。

L120205X1

环绕增强,在L120204X2基础上修改代码

1、将AfterLogger.java名字改为AroundLogger.java

里面的方法为

public class AroundLogger {

private static final Logger log = Logger.getLogger(AroundLogger.class);

public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable {

log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()

+ " 方法。方法入参:" + Arrays.toString(jp.getArgs()));

try {

Object result = jp.proceed();

log.info("调用 " + jp.getTarget() + " 的 "

+ jp.getSignature().getName() + " 方法。方法返回值:" + result);

return result;

} catch (Throwable e) {

log.error(jp.getSignature().getName() + " 方法发生异常:" + e);

throw e;

} finally {

log.info(jp.getSignature().getName() + " 方法结束执行。");    } }}

2、applicationContext.xml配置为

<bean id="dao" class="dao.impl.UserDaoImpl"></bean>

<bean id="service" class="service.impl.UserServiceImpl">

<property name="dao" ref="dao"></property>

</bean>

<!-- 声明增强方法所在的Bean -->

<bean id="theLogger" class="aop.AroundLogger"></bean>

<!-- 配置切面 -->

<aop:config>

<!-- 定义切入点 -->

<aop:pointcut id="pointcut" expression="execution(* service.UserService.*(..))" />

<!-- 引用包含增强方法的Bean -->

<aop:aspect ref="theLogger">

<!-- 将aroundLogger()方法定义为环绕增强并引用pointcut切入点 -->

<aop:around method="aroundLogger" pointcut-ref="pointcut"/>

</aop:aspect>

</aop:config>

3、运行结果为

-调用 service.impl.UserServiceImpl@7bb07f97 的 addNewUser 方法。方法入参:[entity.User@45f177b]

保存用户信息到数据库

10-25 21:41:05[INFO]aop.AroundLogger

-调用 service.impl.UserServiceImpl@7bb07f97 的 addNewUser 方法。方法返回值:null

10-25 21:41:05[INFO]aop.AroundLogger

-addNewUser 方法结束执行。

L120206X1

使用注解实现IOC配置

技术图片

1、user代码

package entity;

public class User implements java.io.Serializable {

private Integer id; // 用户ID

private String username; // 用户名

private String password; // 密码

private String email; // 电子邮件

// getter & setter

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String getEmail() {

return email;

}

public void setEmail(String email) {

this.email = email;

}

}

2、UserDao代码

package dao;

import entity.User;

public interface UserDao {

public void save(User user);

}

3、UserDaoImpl.java代码

package dao.impl;

import org.springframework.stereotype.Repository;

import dao.UserDao;

import entity.User;

@Repository("userDao")

public class UserDaoImpl implements UserDao {

public void save(User user) {

// 这里并未实现完整的数据库操作,仅为说明问题

System.out.println("保存用户信息到数据库");

}

}

4、UserService.java代码

package service;

import entity.User;

public interface UserService {

public void addNewUser(User user);

}

5、UserServiceImpl.java代码

package service.impl;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import service.UserService;

import dao.UserDao;

import entity.User;

@Service("userService")

public class UserServiceImpl implements UserService {

// 声明接口类型的引用,和具体实现类解耦合

@Autowired

private UserDao dao;

public void setDao(UserDao dao) {

this.dao = dao;

}

public void addNewUser(User user) {

// 调用用户DAO的方法保存用户信息

dao.save(user);

}

}

6、Test.java代码

package test;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import service.UserService;

import entity.User;

public class Test {

@org.junit.Test

public void test() {

// 使用ApplicationContext接口的实现类ClassPathXmlApplicationContext加载Spring配置文件

ApplicationContext ctx = new ClassPathXmlApplicationContext(

"applicationContext.xml");

// 通过ApplicationContext接口的getBean()方法获取id或name为userService的Bean实例

UserService service = (UserService) ctx.getBean("userService");

User user = new User();

user.setId(1);

user.setUsername("test");

user.setPassword("123456");

user.setEmail("test@xxx.com");

service.addNewUser(user);

}

}

7、applicationContext.xml代码

<?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:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.2.xsd">

<context:component-scan base-package="service,dao"></context:component-scan>

</beans>

8、运行结果

保存用户信息到数据库

L120206X2

在L120206X1基础上做以下修改

1、将UserDaoImpl.java复制粘贴一份,取名为UserDaoImpl2.java,里面代码为

package dao.impl;

import org.springframework.stereotype.Repository;

import dao.UserDao;

import entity.User;

@Repository("userDao2")

public class UserDaoImpl2 implements UserDao {

public void save(User user) {

// 这里并未实现完整的数据库操作,仅为说明问题

System.out.println("保存用户信息到数据库");}}

2、运行Test.java获得以下异常结果

type [dao.UserDao] is defined: expected single matching bean but found 2: userDao,userDao2

3、如何解决?将UserServiceImpl.java的代码修改成以下代码

package service.impl;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.stereotype.Service;

import service.UserService;

import dao.UserDao;

import entity.User;

@Service("userService")

public class UserServiceImpl implements UserService {

// 声明接口类型的引用,和具体实现类解耦合

@Autowired//按类型装配

@Qualifier("userDao")//指定装配的bean的名称

private UserDao dao;

public void setDao(UserDao dao) {

this.dao = dao;

}

public void addNewUser(User user) {

// 调用用户DAO的方法保存用户信息

dao.save(user);}}

4、运行结果

保存用户信息到数据库

5、如果将UserServiceImpl.java代码中的set方法注释掉进行测试

/*public void setDao(UserDao dao) {

this.dao = dao;

}*/

结果同样可以测试成功

6、@Qualifier("userDao")放入set方法里面,UserServiceImpl.java代码为

package service.impl;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.stereotype.Service;

import service.UserService;

import dao.UserDao;

import entity.User;

@Service("userService")

public class UserServiceImpl implements UserService {

// 声明接口类型的引用,和具体实现类解耦合

private UserDao dao;

@Autowired//按类型装配

//指定装配的bean的名称

public void setDao(@Qualifier("userDao")UserDao dao) {

this.dao = dao;

}

public void addNewUser(User user) {

// 调用用户DAO的方法保存用户信息

dao.save(user);

}

}

测试结果同样成功

7、将example4复制粘贴一份取名为example4_2,用构造方法测试,UserServiceImpl.java中代码修改成以下代码后运行测试类

package service.impl;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.stereotype.Service;

import service.UserService;

import dao.UserDao;

import entity.User;

@Service("userService")

public class UserServiceImpl implements UserService {

// 声明接口类型的引用,和具体实现类解耦合

private UserDao dao;

@Autowired//按类型装配

public UserServiceImpl(@Qualifier("userDao")UserDao dao) {

this.dao = dao;

}

public UserServiceImpl() {

}

public void addNewUser(User user) {

// 调用用户DAO的方法保存用户信息

dao.save(user);}}

结果:保存用户信息到数据库

8、测试没有userDao的情况下的结果

将UserServiceImpl.java中的带参构造改成以下代码

@Autowired//按类型装配

public UserServiceImpl(@Qualifier("userDao3")UserDao dao) {

this.dao = dao;

}

测试结果报错

将UserServiceImpl.java中的带参构造改成以下代码

@Autowired(required=false)//按类型装配

public UserServiceImpl(@Qualifier("userDao3")UserDao dao) {

this.dao = dao;}

运行结果:

Console中没有结果

JUnit中的结果报:java.lang.NullPointerException

因为@Autowired(required=false),required值默认为true

9、复制粘贴example4改名为example5

删除UserDaoImpl2.java,删除UserServiceImpl.java中的@Autowired配置,进行@Resource配置,配置后的代码

package service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import service.UserService;

import dao.UserDao;

import entity.User;

@Service("userService")

public class UserServiceImpl implements UserService {

// 声明接口类型的引用,和具体实现类解耦合

@Resource(name="userDao")//通过@Resource注解进行装配

private UserDao dao;

//指定装配的bean的名称

public void setDao(UserDao dao) {

this.dao = dao;

}

public void addNewUser(User user) {

// 调用用户DAO的方法保存用户信息

dao.save(user);

}

}

运行结果:保存用户信息到数据库

再将上面的name属性删除掉,删除后的构造代码

@Service("userService")

public class UserServiceImpl implements UserService {

// 声明接口类型的引用,和具体实现类解耦合

@Resource//通过@Resource注解进行装配

private UserDao dao;

//指定装配的bean的名称

public void setDao(UserDao dao) {

this.dao = dao;

}

public void addNewUser(User user) {

// 调用用户DAO的方法保存用户信息

dao.save(user);

}

}

先根据属性名dao去找,找不到就根据userDao去找

运行结果:保存用户信息到数据库

10、复制粘贴UserDaoImpl.java改名为UserDaoImpl2.java,里面的代码改成为

package dao.impl;

import org.springframework.stereotype.Repository;

import dao.UserDao;

import entity.User;

@Repository("dao")

public class UserDaoImpl2 implements UserDao {

public void save(User user) {

// 这里并未实现完整的数据库操作,仅为说明问题

System.out.println("保存用户信息到数据库成功!!!");

}

}

运行结果:保存用户信息到数据库成功!!!

11、将@Resource放在set方法前

@Service("userService")

public class UserServiceImpl implements UserService {

// 声明接口类型的引用,和具体实现类解耦合

private UserDao dao;

//指定装配的bean的名称

@Resource(name="userDao")//通过@Resource注解进行装配

public void setDao(UserDao dao) {

this.dao = dao;

}

public void addNewUser(User user) {

// 调用用户DAO的方法保存用户信息

dao.save(user);

}

}

运行结果:保存用户信息到数据库

如果删除name属性则运行结果为:保存用户信息到数据库成功!!!

如果将setDao(UserDao dao)改成setUserDao(UserDao dao)

@Resource//通过@Resource注解进行装配

public void setUserDao(UserDao dao) {

this.dao = dao;

}

运行结果为:保存用户信息到数据库,说明是按照setUserDao而不是dao属性名

12、如果将UserServiceImpl.java代码改成

@Service("userService")

public class UserServiceImpl implements UserService {

// 声明接口类型的引用,和具体实现类解耦合

@Resource//通过@Resource注解进行装配

private UserDao dao1;

//指定装配的bean的名称

public void setUserDao(UserDao dao) {

this.dao1 = dao;

}

public void addNewUser(User user) {

// 调用用户DAO的方法保存用户信息

dao1.save(user);

}

}

运行结果为 expected single matching bean but found 2: userDao,dao

找到两个,原因是根据dao1去找找不到就根据类型去找,找到两个userDao类型的,删除UserDaoImpl2.java运行便不报错了

L120207X1

技术图片

修改UserSercviceLogger.java和applicationContext.xml代码其他保存不变

一、测试前置增强

1、UserSercviceLogger.java代码

@Aspect

public class UserSercviceLogger {

private static Logger log=Logger.getLogger(UserSercviceLogger.class);

@Before("execution(* service.UserService.*(..))")

public void before(JoinPoint jp){

log.info("调用"+jp.getTarget()+"的"+jp.getSignature()

+"方法,方法参数"+Arrays.toString(jp.getArgs()));

}

public void afterReturning(JoinPoint jp,Object result){

log.info("调用"+jp.getTarget()+"的"+jp.getSignature()

+"方法,方法参数"+result); }}

2、applicationContext.xml代码

<?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: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-3.2.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.2.xsd

http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">

<context:component-scan base-package="service,dao"></context:component-scan>

<bean class="aop.UserSercviceLogger"></bean>

<!-- 启动spring AOP的Aspect注解的支持 -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

</beans>

3、运行结果为

-调用service.impl.UserServiceImpl@2991c9a6的void service.UserService.addNewUser(User)方法,方法参数[entity.User@6bfbcd1b]

保存用户信息到数据库

二、测试后置增强

1、将UserSercviceLogger.java中后置增强代码改为

@AfterReturning(pointcut="execution(* service.UserService.*(..))",returning="result")

public void afterReturning(JoinPoint jp,Object result){

log.info("调用"+jp.getTarget()+"的"+jp.getSignature()

+"方法,方法参数"+result);

}

2、运行结果

-调用service.impl.UserServiceImpl@5e91af0f的void service.UserService.addNewUser(User)方法,方法参数[entity.User@2551050]

保存用户信息到数据库

10-27 15:17:40[INFO]aop.UserSercviceLogger

-调用service.impl.UserServiceImpl@5e91af0f的void service.UserService.addNewUser(User)方法,方法参数null

三、将切入点统一使用

1、将UserSercviceLogger.java改为

@Aspect

public class UserSercviceLogger {

private static Logger log=Logger.getLogger(UserSercviceLogger.class);

@Pointcut("execution(* service.UserService.*(..))")

public void pointcut(){}

@Before("pointcut()")

public void before(JoinPoint jp){

log.info("调用"+jp.getTarget()+"的"+jp.getSignature()

+"方法,方法参数"+Arrays.toString(jp.getArgs()));

}

@AfterReturning(pointcut="pointcut()",returning="result")

public void afterReturning(JoinPoint jp,Object result){

log.info("调用"+jp.getTarget()+"的"+jp.getSignature()

+"方法,方法参数"+result);

}

}

2、测试运行结果

与二中的结果一样

四、测试异常抛出增强

1、复制粘贴example6名字改为example7

将L120204X1exampleAfterThrowing中的ErrorLogger.java复制粘贴在example7中,删除UserSercviceLogger.java

2、ErrorLogger.java中代码为

@Aspect

public class ErrorLogger {

private static Logger log=Logger.getLogger(ErrorLogger.class);

@AfterThrowing(pointcut="execution(* service.UserService.*(..))",throwing="e")

public void afterThrowing(JoinPoint jp,RuntimeException e){

log.error(jp.getSignature().getName()+"方法发成异常"+e);

}

}

3、UserDaoImpl.java中代码

@Repository("userDao")

public class UserDaoImpl implements UserDao {

public void save(User user) {

System.out.println("保存用户信息到数据库");

throw new RuntimeException("为测试程序运行效果抛出的异常");

}

}

3、applicationContext.xml中bean元素改为

<bean class="aop.ErrorLogger"></bean>

4、运行结果为

保存用户信息到数据库

10-27 15:49:58[ERROR]aop.ErrorLogger

-addNewUser方法发成异常java.lang.RuntimeException: 为测试程序运行效果抛出的异常

五、最终增强

1、复制粘贴example7,命名为example8,将使用Schema定义最终增强中的AfterLogger.java复制粘贴在example8中,删除ErrorLogger.java

2、AfterLogger.java中代码为

@Aspect

public class AfterLogger {

private static final Logger log = Logger.getLogger(AfterLogger.class);

@After("execution(* service.UserService.*(..))")

public void afterLogger(JoinPoint jp) {

log.info(jp.getSignature().getName() + " 方法结束执行。");

}

}

3、applicationContext.xml中bean元素改为

<bean class="aop.AfterLogger"></bean>

4、在有异常抛出的情况下运行结果

保存用户信息到数据库

10-27 16:59:02[INFO]aop.AfterLogger

-addNewUser 方法结束执行。

六、环绕增强

2、复制粘贴example8,命名为example9,将使用Schema定义环绕增强中的AroundLogger.java复制粘贴在example9中,删除AfterLogger.java

2、AroundLogger.java中代码为

@Aspect

public class AroundLogger {

private static final Logger log = Logger.getLogger(AroundLogger.class);

@Around("execution(* service.UserService.*(..))")

public Object aroundLogger(ProceedingJoinPoint jp) throws Throwable {

log.info("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()

+ " 方法。方法入参:" + Arrays.toString(jp.getArgs()));

try {

Object result = jp.proceed();

log.info("调用 " + jp.getTarget() + " 的 "

+ jp.getSignature().getName() + " 方法。方法返回值:" + result);

return result;

} catch (Throwable e) {

log.error(jp.getSignature().getName() + " 方法发生异常:" + e);

throw e;

} finally {

log.info(jp.getSignature().getName() + " 方法结束执行。");

        }

}

}

3、applicationContext.xml中bean元素改为

<bean class="aop.AroundLogger"></bean>

4、在有异常抛出的情况下运行结果

-调用 service.impl.UserServiceImpl@68dda0a 的 addNewUser 方法。方法入参:[entity.User@291c9a1e]

保存用户信息到数据库

10-27 17:08:07[ERROR]aop.AroundLogger

-addNewUser 方法发生异常:java.lang.RuntimeException: 为测试程序运行效果抛出的异常

10-27 17:08:07[INFO]aop.AroundLogger

-addNewUser 方法结束执行。

以上是关于IOC和AOP扩展的主要内容,如果未能解决你的问题,请参考以下文章

Spring IoC和AOP使用扩展

Day643.IoC和AOP是扩展的核心 -Java业务开发常见错误

IoC和AOP使用扩展。。。

Ioc和AOP使用扩展

IOC和AOP使用扩展 多种方式实现依赖注入

Dubbo之SPI源码分析