pom.xml的内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>cn.itcastgroupId>
<artifactId>spring4_day02artifactId>
<version>0.0.1-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.5.1version>
<configuration>
<source>1.7source>
<target>1.7target>
configuration>
plugin>
plugins>
build>
project>
n 引入applicationContext.xml和log4j.properties
n 创建UserService接口
package cn.itcast.service;
public interface UserService {
/**
* 业务层:用户保存
*/
public void saveUser();
}
n 创建UserService的实现类UserServiceImpl
package cn.itcast.service.impl;
import cn.itcast.service.UserService;
public class UserServiceImpl implements UserService {
@Override
public void saveUser() {
System.out.println("业务层:用户保存...");
}
}
n 在UserServiceImpl实现类上添加注解@Component,相当于
@Component("userService")
public class UserServiceImpl implements UserService{
@Override
public void saveUser() {
System.out.println("业务层:用户保存...");
}
}
注意:因为现在想使用注解,那么引入的约束发生了变化,需要context的约束。
【提示】:约束可以从spring开发文档中拷贝,也可以从笔记里拷贝。如果从spring开发文档中拷贝,可以参考spring开发文档的6.9节
添加完context约束之后的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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
beans>
在applicationContext.xml通过context:component-scan标签开启spring注解扫描,扫描时是以包范围来扫描的:
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
beans>
/**
* 测试注解
*/
@Test
public void test1(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.saveUser();
}
Spring中用于管理bean的注解分为四大类:
1、用于创建对象
2、用于给对象中的属性注入值
3、用于改变作用范围
4、用于定义生命周期
用于创建对象的有四个:@Component,@Controller,@Service,@Repository
作用:
把资源让spring来管理。相当于在xml中配置一个bean。
属性:
value:指定bean的id。如果不指定value属性,默认bean的id是当前类的类名。首字母小写。
他们三个注解都是针对一个的衍生注解,他们的作用及属性都是一模一样的。
他们只不过是提供了更加明确的语义化。
@Controller:一般用于表现层的注解。
@Service:一般用于业务层的注解。
@Repository:一般用于持久层的注解。
@Service的用法:修改UserServiceImpl类,把@Component改成@Service
//@Component("userService")
@Service("userService")
public class UserServiceImpl implements UserService{
@Override
public void saveUser() {
System.out.println("业务层:用户保存...");
}
}
@Repository的用法:
创建UserDao接口:
@Repository("userDao")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("持久层:用户保存...");
}
}
注意:此处测试时,要把扫描的包定义为cn.itcast,不然的其它包的注解就不能识别了
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
beans>
@Controller的用法:创建UserAction类,在该类上加@Controller注解
@Controller("userAction")
public class UserAction {
}
说明:这三个注解是为了让标注类本身的用途清晰
用于注入数据的注解有:
1、@Value
2、@Autowired
3、@Qualifier
4、@Resource
相当于:
作用:
注入基本数据类型和String类型数据的
属性:
value:用于指定值
修改UserServiceImpl类,增加一个字符串属性name,现在要通过@Value给name属性注入值
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("张三")
private String name;
@Override
public void saveUser() {
System.out.println("业务层:用户保存..." + name);
}
}
运行TestIOC中的test1方法,测试结果如下:
作用:
自动按照类型注入。当使用注解注入属性时,set方法可以省略。它只能注入其他bean类型。当有多个类型匹配时,使用要注入的对象变量名称作为bean的id,在spring容器查找,找到了也可以注入成功。找不到就报错。
修改UserServiceImpl类,增加一个对象属性userDao,现在通过@Autowired给userDao注入值
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("张三")
private String name;
@Autowired
private UserDao userDao;
@Override
public void saveUser() {
System.out.println("业务层:用户保存..." + name);
userDao.save();
}
}
运行TestIOC中的test1方法,测试结果如下:
作用:
在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowire一起使用;但是给方法参数注入时,可以独立使用。
属性:
value:指定bean的id。
n 创建UserDao接口的第二个实现类UserDaoImpl2
@Repository("userDao2")
public class UserDaoImpl2 implements UserDao {
@Override
public void save() {
System.out.println("持久层:用户保存2222...");
}
}
运行TestIOC中的test1方法,测试结果如下:
n 测试发现,UserServiceImpl中注入的还是第一个UserDaoImpl,因为当有多个bean都满足的情况下,优先注入bean的id与属性的名字一样的bean;想指定注入UserDaoImpl2,需要使用@Qualifier注解根据名字来注入
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("张三")
private String name;
@Autowired
@Qualifier("userDao2")
private UserDao userDao;
@Override
public void saveUser() {
System.out.println("业务层:用户保存..." + name);
userDao.save();
}
}
再次运行TestIOC中的test1方法,发现UserServiceImpl中注入的是UserDaoImpl2;测试结果如下:
作用:
直接按照Bean的id注入。它也只能注入其他bean类型。
属性:
name:指定bean的id。
修改UserServiceImpl类,使用@Resource给userDao注入值。@Resource是按照bean的id来注入,只能注入对象类型
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("张三")
private String name;
//@Autowired
//@Qualifier("userDao2")
@Resource(name="userDao2")
private UserDao userDao;
@Override
public void saveUser() {
System.out.println("业务层:用户保存..." + name);
userDao.save();
}
}
作用:
指定bean的作用范围。
属性:
value:指定范围的值。
取值:singleton prototype request session globalsession
n @Scope指定bean的作用域,默认值是singleton,单例的。
n 修改UserServiceImpl,在该类上加@Scope注解,指定该类是多例的的,默认是单例的。给该类显示指定一个无参构造方法,方便测试
@Service("userService")
@Scope("prototype")
public class UserServiceImpl implements UserService{
@Value("张三")
private String name;
//@Autowired
//@Qualifier("userDao2")
@Resource(name="userDao2")
private UserDao userDao;
public UserServiceImpl() {
System.out.println("调用了无参构造方法...");
}
@Override
public void saveUser() {
System.out.println("业务层:用户保存..." + name);
userDao.save();
}
}
n 在TestIOC中创建test2单元测试方法
@Test
public void test2(){
//创建ioc容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService1 = (UserService) ac.getBean("userService");
UserService userService2 = (UserService) ac.getBean("userService");
System.out.println(userService1 == userService2);
}
n 测试发现:当scope指定为prototype时,两次获取UserService的对象是不一致的。测试结果如下:
相当于:
@PostConstruct加在方法上,指定bean对象创建好之后,调用该方法初始化对象,类似于xml的init-method方法。修改UserServiceImpl类,在其中增加一个init方法,在该方法上指定@PostConstruct注解
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("张三")
private String name;
//@Autowired
//@Qualifier("userDao2")
@Resource(name="userDao2")
private UserDao userDao;
public UserServiceImpl() {
System.out.println("调用了无参构造方法...");
}
@PostConstruct
public void init(){
System.out.println("调用了init方法...");
}
@Override
public void saveUser() {
System.out.println("业务层:用户保存..." + name);
userDao.save();
}
}
运行TestIOC中的test1方法,测试结果如下:
@PreDestory加在方法上,指定bean销毁之前,调用该方法,类似于xml的destory-method方法。修改UserServiceImpl类,在该类中增加一个destroy方法,在该方法上加@PreDestroy注解
@Service("userService")
public class UserServiceImpl implements UserService {
@Value("张三")
private String name;
//@Autowired
//@Qualifier("userDao2")
@Resource(name="userDao2")
private UserDao userDao;
public UserServiceImpl() {
System.out.println("调用了无参构造方法...");
}
@PostConstruct
public void init(){
System.out.println("调用了init方法...");
}
@Override
public void saveUser() {
System.out.println("业务层:用户保存..." + name);
userDao.save();
}
@PreDestroy
public void destroy(){
System.out.println("调用了destroy方法...");
}
}
注意:要看到@PreDestory的效果,需要调用ClassPathXmlApplicationContext.close方法,同时scope的值要是singleton。所以,还得修改test1方法,显示关闭ioc容器
@Test
public void test1(){
//创建ioc容器
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService = (UserService) ac.getBean("userService");
userService.saveUser();
((ClassPathXmlApplicationContext)ac).close();
}
测试结果如下:
注解小结:
与创建bean对象
@Component
@Controller
@Service
@Repository
与注入值相关
@Autowired
@Qualifier
@Resource
@Value
与范围相关
@Scope
与生命周期相关
@PostConstruct
@PreDestroy
注解的优势:
配置简单,维护方便。(我们找到了类,就相当于找到了配置)
XML的优势:
修改时,不用改源码。不涉及重新编译和部署。
Xml和注解的比较
需要引入的依赖有:spring ioc+c3p0+mysql+dbutils。完整的pom.xml内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>cn.itcastgroupId>
<artifactId>spring4_day02_springAndDBUtilsartifactId>
<version>0.0.1-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>4.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.12version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.18version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>commons-dbutilsgroupId>
<artifactId>commons-dbutilsartifactId>
<version>1.7version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.5.1version>
<configuration>
<source>1.7source>
<target>1.7target>
configuration>
plugin>
plugins>
build>
project>
创建CustomerService接口
public interface CustomerService {
/**
* 业务层:查询所有客户
* @return
*/
public List
}
创建CustomerService接口的实现类CustomerServiceImpl
public class CustomerServiceImpl implements CustomerService {
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
@Override
public List
List
return list;
}
}
创建UserDao接口
public interface CustomerDao {
public List
}
创建UserDao接口的实现类
public class CustomerDaoImpl implements CustomerDao {
private QueryRunner queryRunner;//不需要实例化,通过spring依赖注入进来
public void setQueryRunner(QueryRunner queryRunner) {
this.queryRunner = queryRunner;
}
@Override
public List
List
try {
list = queryRunner.query("select * from cst_customer", new BeanListHandler
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
在src下创建spring的配置文件applicationContext.xml,把Service、Dao、QueryRunner、DataSource配置到Spring中
1、Service中需要注入DAO
2、DAO中需要注入QueryRunner
3、QueryRunner中需要注入DataSource
4、DataSource中需要注入驱动、连接地址、用户名、密码
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.xsd">
<bean id="customerService" class="cn.itcast.service.impl.CustomerServiceImpl">
<property name="customerDao" ref="customerDao">property>
bean>
<bean id="customerDao" class="cn.itcast.dao.impl.CustomerDaoImpl">
<property name="queryRunner" ref="queryRunner">property>
bean>
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource">constructor-arg>
bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver">property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/hibernate">property>
<property name="user" value="root">property>
<property name="password" value="123456">property>
bean>
beans>
注意:还得引入log4j.properties文件
创建单元测试类TestFind,在其中创建test1方法
@Test
public void test1(){
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
CustomerService customerService = (CustomerService) ac.getBean("customerService");
List
for (Customer customer : customers) {
System.out.println(customer);
}
}
测试结果如下:
修改CustomerServiceImpl类,在该类上加@Service注解。在customerDao上加@Autowired注解,表示给该属性注入值
@Service("customerService")
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerDao customerDao;
@Override
public List
List
return list;
}
}
修改CustomerDaoImpl类,在该类上加@Repository注解。在queryRunner上加@Autowired注解,表示给该属性注入值。
@Repository("customerDao")
public class CustomerDaoImpl implements CustomerDao {
@Autowired
private QueryRunner queryRunner;
@Override
public List
List
try {
list = queryRunner.query("select * from cst_customer", new BeanListHandler
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}
在applicationContext.xml中开启spring注解扫描。
注意:QueryRunner和DataSource这两个bean暂时没有办法用注解来配置,因为属于jar包里的bean.
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner">
<constructor-arg name="ds" ref="dataSource">constructor-arg>
bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver">property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/hibernate">property>
<property name="user" value="root">property>
<property name="password" value="123456">property>
bean>
beans>
再次运行TestFind中的test1方法,结果和xml的配置是一样的。
为了简化了JUnit的测试,使用Spring框架也可以整合测试。
要求:必须先有JUnit的环境(默认会使用Eclipse导入单元测试的环境)!!
可以直接在spring4_day02中引入spring-test.jar包的依赖,把spring4_day02中的单元测试类全部改成spring的写法
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>cn.itcastgroupId>
<artifactId>spring4_day02artifactId>
<version>0.0.1-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>4.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.12version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.5.1version>
<configuration>
<source>1.7source>
<target>1.7target>
configuration>
plugin>
plugins>
build>
project>
修改单元测试类TestIOC,在该类上添加@RunWith和@ContextConfiguration两个注解。我们需要测试的是UserService,在TestIOC中声明一个UserService的属性,并在该属性上添加@Autowired注解,为该属性注入值。修改后的TestIOC如下:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class TestIOC {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.saveUser();
}
}
n @RunWith注解:这个是指定使用的单元测试执行类,这里就指定的是SpringJUnit4ClassRunner.class;
@ContextConfiguration注解:这个指定spring配置文件所在的路径,可以同时指定多个文件;
横向抽取机制(AOP思想):
AOP 思想: 基于代理思想,对原来目标对象,创建代理对象,在不修改原对象代码情况下,通过代理对象,调用增强功能的代码,从而对原有业务方法进行增强 !
场景一: 记录日志
场景二: 监控方法运行时间 (监控性能)
场景三: 权限控制
场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第二次调用, 直接从内存对象返回,不需要查询数据库 )
场景五: 事务管理 (调用方法前开启事务, 调用方法后提交关闭事务 )
那Spring中AOP是怎么实现的呢?Spring中AOP的有两种实现方式:
1、JDK动态代理
Cglib动态代理
n 创建maven工程并引入依赖,pom.xml内容如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>cn.itcastgroupId>
<artifactId>spring4_day02_myaopartifactId>
<version>0.0.1-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>4.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.12version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.5.1version>
<configuration>
<source>1.7source>
<target>1.7target>
configuration>
plugin>
plugins>
build>
project>
n 创建CustomerDao接口
public class CustomerDaoImpl implements CustomerDao {
@Override
public void save() {
System.out.println("持久层:客户保存...");
}
}
n 现在需要对CustomerDaoImpl增强,创建JdkProxy,用于创建CustomerDaoImpl的增强对象。注意:JDK动态代理只能对实现了接口的类产生代理。
public class JdkProxy implements InvocationHandler{
private CustomerDao customerDao;//要增强的目标
public JdkProxy(CustomerDao customerDao) {
this.customerDao = customerDao;
}
/**
* 利用jdk动态代理生成对象的方法
* newProxyInstance的三个参数:
* loader:代理类的类加载器(和目标象使用相同的类加载器)
* interfaces:代理类要实现的接口列表(和目标对象具有相同的行为,实现相同的接口)
* handler:回调
* @return
*/
public CustomerDao create(){
CustomerDao proxy = (CustomerDao) Proxy.newProxyInstance(customerDao.getClass().getClassLoader(), customerDao.getClass().getInterfaces(),this);
return proxy;
}
/**
* 当你调用目标方法时,其实是调用该方法
* invoke中的三个参数:
* proxy:代理对象
* method:目标方法
* args:目标方法的形参
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//添加一个记录日志的功能
System.out.println("记录日志...");
//调用目标的方法
Object result = method.invoke(customerDao, args);
return result;
}
}
n 创建TestProxy单元测试类,在其中创建test1单元测试方法:
@Test
public void test1(){
//目标
CustomerDao customerDao = new CustomerDaoImpl();
JdkProxy jdkProxy = new JdkProxy(customerDao);
CustomerDao proxy = (CustomerDao) jdkProxy.create();
proxy.save();
}
测试结果如下:
在实际开发中,可能需要对没有实现接口的类增强,用JDK动态代理的方式就没法实现。采用Cglib动态代理可以对没有实现接口的类产生代理,实际上是生成了目标类的子类来增强。
n 首先,需要导入Cglib所需的jar包。提示:spring已经集成了cglib,我们已经导入了spring包,故不需要再导入其它包了。
n 创建LinkManDao类,没有实现任何接口
public class LinkManDao {
public void save(){
System.out.println("持久层:联系人保存...");
}
}
n 创建CglibProxy,为LinkManDao来生成增强对象
public class CglibProxy implements MethodInterceptor{
private LinkManDao linkManDao;
public CglibProxy(LinkManDao linkManDao) {
this.linkManDao = linkManDao;
}
public LinkManDao create(){
//创建cglib的核心对象
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(linkManDao.getClass());
//设置回调
enhancer.setCallback(this);
//创建代理对象
LinkManDao proxy = (LinkManDao) enhancer.create();
return proxy;
}
/**
* 当你调用目标方法时,实质上是调用该方法
* intercept四个参数:
* proxy:代理对象
* method:目标方法
* args:目标方法的形参
* methodProxy:代理方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//添加检测权限的功能
System.out.println("记录日志...");
//调用目标(父类)方法
//Object result = method.invoke(linkManDao, args);
Object result = methodProxy.invokeSuper(proxy, args);
return result;
}
}
n 在TestProxy中创建单元测试方法test2
@Test
public void test2(){
//目标
LinkManDao linkManDao = new LinkManDao();
CglibProxy cglibProxy = new CglibProxy(linkManDao);
LinkManDao proxy = cglibProxy.create();
proxy.save();
}
测试结果如下: