目录
3、配置文件applicationContext.xml :
一、静态代理
代理:
- 在不修改目标类的目标方法代码前提下,为目标方法增加额外的功能
- 代理类中也必须有同样的目标方法
- 代理类实现跟目标类同样的接口
- 如果目标类没有实现接口,代理类继承目标类
- 基本上每个目标类都要编写一个代理类
核心是要手动创建一个代理类来实现service,然后配置文件中:注入的bean变成代理类,代理类中的target属性变成实现类。
1、代理类:
package com.mj.proxy;
import com.mj.service.UserService;
public class UserServiceProxy implements UserService {
private UserService target;
public void setTarget(UserService target) {
this.target = target;
}
public boolean login(String username, String password) {
System.out.println("这里写附加代码1");
target.login(username,password);
System.out.println("这里写附加代码2");
return false;
}
}
package com.mj.proxy;
import com.mj.service.SkillService;
public class SkillServiceProxy extends SkillService {
private SkillService target;
public void setTarget(SkillService target) {
this.target = target;
}
@Override
public boolean save(Object skill) {
System.out.println("SkillServiceProxy ----- 1");
boolean result = target.save(skill);
System.out.println("SkillServiceProxy ----- 2");
return result;
}
}
2、配置文件:
<?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="userService" class="com.mj.proxy.UserServiceProxy">
<property name="target" >
<bean class="com.mj.service.impl.UserServiceImpl"/>
</property>
</bean>
<bean id="skillService" class="com.mj.proxy.SkillServiceProxy">
<property name="target" >
<bean class="com.mj.service.SkillService"/>
</property>
</bean>
</beans>
3、实现类:
package com.mj.service.impl;
import com.mj.service.UserService;
public class UserServiceImpl implements UserService {
public boolean login(String username, String password) {
System.out.println("--login " + username + password);
return false;
}
}
package com.mj.service;
public class SkillService {
public boolean save(Object skill) {
System.out.println("SkillService --- save");
return false;
}
}
4、测试类:
@Test
public void test(){
// 创建容器
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = ctx.getBean("userService", UserService.class);
boolean result = service.login("小马哥","123456");
// 关闭容器
ctx.close();
// 创建容器
ClassPathXmlApplicationContext ctx1 = new ClassPathXmlApplicationContext("applicationContext.xml");
SkillService service1 = ctx1.getBean("skillService", SkillService.class);
service1.save(null);
// 关闭容器
ctx1.close();
}
五、代码结构如下图:
二、动态代理
动态代理有两种方案,一种是jdk的一种是cglib方案:
- jdk自带的方案:必须要写加载器,并且只能对接口动态代理
- cglib方案:内部会传一个类加载器,并且不只是对接口进行动态代理
1、创建service以及serviceImpl如下:
- personService: void run();方法
- userService: boolean login(String username, String password);方法
- skillService是一个类:
public class SkillService { public boolean save(Object skill) { System.out.println("SkillService --- save"); return false; } }
2、创建domain如下:
创建Person类以及相关方法如下:
public class Person { public void eat() { System.out.println("Person --- eat"); } }
3、配置文件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.xsd">
<!-- <bean class="com.mj.processor.LogProcessor"/>-->
<bean class="com.mj.processor.LogProcessor2"/>
<bean id="userService" class="com.mj.service.impl.UserServiceImpl"/>
<bean id="personService" class="com.mj.service.impl.PersonServiceImpl"/>
<bean id="skillService" class="com.mj.service.SkillService"/>
<bean id="person" class="com.mj.domain.Person"/>
</beans>
4、processor如下:
- jdk自带的动态代理相关配置:
package com.mj.processor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 会拦截每一个bean的生命周期,这个是jdk自带的动态代理方案,必须要写加载器,并且只能对接口动态代理 */ public class LogProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException { return Proxy.newProxyInstance(getClass().getClassLoader(), // 类加载器,必须要有 target.getClass().getInterfaces(), // 代理类需要实现的接口(目标类的接口),必须要有接口不然会报错 new LogInvocationHandler(target)); // 附加代码 } private static class LogInvocationHandler implements InvocationHandler { private Object target; public LogInvocationHandler(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // proxy: 代理对象 // method:目标方法 // args:目标方法的参赛 System.out.println("proxy111-----------------1"); // 调用目标对象的目标方法(核心业务代码) Object result = method.invoke(target,args); System.out.println("proxy222-----------------2"); return result; } } }
cglib动态代理相关配置:
package com.mj.processor; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * 会拦截每一个bean的生命周期,CGlib方案,内部会传一个类加载器,并且不只是对接口进行动态代理 */ public class LogProcessor2 implements BeanPostProcessor { public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException { // 有些需要过滤 if (!beanName.endsWith("Service")) return target; Enhancer enhancer = new Enhancer(); enhancer.setClassLoader(getClass().getClassLoader());// cglib可以不要 enhancer.setSuperclass(target.getClass()); enhancer.setCallback(new LogMethodInterceptor(target)); return enhancer.create(); } private static class LogMethodInterceptor implements MethodInterceptor { private Object target; public LogMethodInterceptor(Object target) { this.target = target; } public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("proxy1-------------------"); Object result = method.invoke(target,args); System.out.println("proxy2-------------------"); return result; } } }
测试工程结构如下图: