前言
- 教程:spring ioc和aop理解
- 时间:2021/11/5
- 整理人:vanse
- 环境:jdk8 spring5.2
- 参考: 马士兵(ioc) briup(aop)
ioc理解
理论
该声明周期在BeanFactory中有规定
* <p>Bean factory implementations should support the standard bean lifecycle interfaces
* as far as possible. The full set of initialization methods and their standard order is:
* <ol>
* <li>BeanNameAware's {@code setBeanName}
* <li>BeanClassLoaderAware's {@code setBeanClassLoader}
* <li>BeanFactoryAware's {@code setBeanFactory}
* <li>EnvironmentAware's {@code setEnvironment}
* <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
* <li>ResourceLoaderAware's {@code setResourceLoader}
* (only applicable when running in an application context)
* <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
* (only applicable when running in an application context)
* <li>MessageSourceAware's {@code setMessageSource}
* (only applicable when running in an application context)
* <li>ApplicationContextAware's {@code setApplicationContext}
* (only applicable when running in an application context)
* <li>ServletContextAware's {@code setServletContext}
* (only applicable when running in a web application context)
* <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
* <li>InitializingBean's {@code afterPropertiesSet}
* <li>a custom init-method definition
* <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
* </ol>
BeanPostProcessor和BeanFactoryPostProcessor (后置处理器/增强器)
- BeanFactoryPostProcessor 增强BeanDefinition
- BeanPostProcessor 增强Bean信息
Spring Bean
- 普通对象 自定义对象(我们需要)
- 容器对象 内置对象 (spring需要)
BeanFactory和FactoryBean
- BeanFactory spring控制
- FactoryBean 用户控制 无须遵循bean的生命周期
- &user 取工厂对象
- user 取user对象
实操
实体类
public class Customer implements InitializingBean, BeanFactoryAware, BeanNameAware, DisposableBean {
private String name;
private String beanName;
private BeanFactory beanFactory;
public Customer() {
System.out.println("【customer】的无参构造器");
}
// 这是BeanNameAware接口方法
@Override
public void setBeanName(String beanName) {
System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
this.beanName = beanName;
}
// 这是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
this.beanFactory = beanFactory;
}
// 这是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
}
// 这是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
}
// 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
}
// 通过<bean>的destroy-method属性指定的销毁方法
public void myDestory() {
System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的销毁方法");
}
public String getName() {
System.out.println("【person】 注入属性 name");
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Customer [name=" + name + ", beanName=" + beanName + ", beanFactory=" + beanFactory + "]";
}
}
MyBeanFactoryPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
// 后置处理器 可干预BeanDefinition
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
System.out.println("【BeanFactoryPostProcessor】构造器!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory factory)
throws BeansException {
System.out
.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
BeanDefinition bd = factory.getBeanDefinition("customer");
bd.getPropertyValues().addPropertyValue("name", "vanse");
}
}
后置处理器 可干预BeanDefinition
MyInstantitationAwareBeanPostProcessor 实例化处理器
import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
public class MyInstantitationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
MyInstantitationAwareBeanPostProcessor(){
System.out.println("【MyInstantitationAwareBeanPostProcessor】构造方法");
}
// 实例化前是beanClass
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if("customer".equals(beanName)) {
System.out.println("实例化前");
}
return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);
}
// 实例化后 是bean
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if("customer".equals(beanName)) {
System.out.println("实例化后");
}
return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
String beanName) throws BeansException {
if("customer".equals(beanName)) {
System.out.println("实例化中设置属性");
}
return InstantiationAwareBeanPostProcessor.super.postProcessPropertyValues(pvs, pds, bean, beanName);
}
}
MyBeanPostProcessor
后置处理器 可干预bean
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor{
public MyBeanPostProcessor() {
System.out.println("【MyBeanPostProcessor】构造方法");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if("customer".equals(beanName)) {
System.out.println("初始化前");
}
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("customer".equals(beanName)) {
System.out.println("初始化后");
}
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
bean.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="beanPostProcessor"
class="com.briup.life.process.MyBeanPostProcessor">
</bean>
<bean id="instantiationAwareBeanPostProcessor"
class="com.briup.life.process.MyInstantitationAwareBeanPostProcessor">
</bean>
<bean id="beanFactoryPostProcessor"
class="com.briup.life.process.MyBeanFactoryPostProcessor">
</bean>
<bean id="customer" class="com.briup.life.entity.Customer"
init-method="myInit" destroy-method="myDestory" scope="singleton">
<property name="name" value="tom"></property>
</bean>
</beans>
测试
public class TestLife {
public static void main(String[] args) {
System.out.println("现在开始初始化容器");
ClassPathXmlApplicationContext context
= new ClassPathXmlApplicationContext("bean.xml");
System.out.println("容器初始化成功");
Customer customer = (Customer) context.getBean("customer");
System.out.println(customer);
System.out.println("现在开始关闭容器!");
context.close();
}
}
结果
现在开始初始化容器
【BeanFactoryPostProcessor】构造器!!
BeanFactoryPostProcessor调用postProcessBeanFactory方法
【MyBeanPostProcessor】构造方法
【MyInstantitationAwareBeanPostProcessor】构造方法
实例化前
【customer】的无参构造器
实例化后
实例化中设置属性
【BeanNameAware接口】调用BeanNameAware.setBeanName()
【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
初始化前
【InitializingBean接口】调用InitializingBean.afterPropertiesSet()
【init-method】调用<bean>的init-method属性指定的初始化方法
初始化后
容器初始化成功
Customer [name=vanse, beanName=customer, beanFactory=org.springframework.beans.factory.support.DefaultListableBeanFactory@10d59286: defining beans [beanPostProcessor,instantiationAwareBeanPostProcessor,beanFactoryPostProcessor,customer]; root of factory hierarchy]
现在开始关闭容器!
【DiposibleBean接口】调用DiposibleBean.destory()
【destroy-method】调用<bean>的destroy-method属性指定的销毁方法
总结
- BeanFactoryPostProcessor 后置设置BeanDefinition
- instantiationAwareBeanPostProcessor 实例化前
- Customer 推断构造方法 创建调用
- instantiationAwareBeanPostProcessor 实例化后
- instantiationAwareBeanPostProcessor 实例化后设置属性
- BeanNameAware接口
- BeanFactoryAware接口
- beanPostProcessor 初始化前
- InitializingBean接口 初始化
- init-method 初始化方法
- beanPostProcessor 初始化后
- DiposibleBean 销毁
- destroy-method 销毁方法
aop理解
代理
代理模式是一种常见的设计模式,它提供间接对目标对象访问的方式,通过代理对象访问目标对象,从而在在目标对象现有的功能能上,增加额外的功能补充,实现扩展目标对象的功能
静态代理
静态代理是代理模式的实现方式之一,在程序运行前,手动创建代理类,从而实现对目标类中的方法进行增强
IUserService
public interface IUserService {
void login();
}
UserServiceImpl
public class UserServiceImpl implements IUserService{
@Override
public void login() {
System.out.println("模拟 用户登录");
}
}
TestStaticProxy
// 不使用代理 功能有限
@Test
public void test() {
IUserService userService = new UserServiceImpl();
userService.login();
}
UserServiceProxy
// 代理类
// 必须含有原方法
// 再增强方法
public class UserServiceProxy implements IUserService{
private UserServiceImpl userServiceImpl;
public UserServiceProxy(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
@Override
public void login() {
System.out.println("访问前时间");
//System.out.println("用户登录");
userServiceImpl.login();
System.out.println("访问后时间");
}
}
TestStaticProxy
// 将来spring 自动注入 @Autowired
@Test
public void test2() {
UserServiceImpl userServiceImpl = new UserServiceImpl();
IUserService userService = new UserServiceProxy(userServiceImpl);
userService.login();
}
动态代理
动态代理则是在程序运行期间,采用字节码技术,动态生成的一个代理对象,从而实现目标对象中方法的增强
jdk
Proxy类中的newProxyInstance 方法,可以在运行启动期间,动态生成指定接口的代理类对象:
public class Proxy implements java.io.Serializable {
/**
* loader,目标类的类加载器
* interfaces,目标类所实现的接口,可以是多个
* InvocationHandler,InvocationHandler接口的实现类对象
*/
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException{
//...增强哪些方法
}
}
java.lang.reflect.InvocationHandler 接口中只有一个抽象方法:
package java.lang.reflect;
public interface InvocationHandler {
/**
* proxy,将来动态生成的代理类对象
* method,将来需要代理的目标对象中的方法
* args,将来调用目标对象方法时所传入的参数列表
*/
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;
}
ICustomerService
public interface ICustomerService {
void login();
}
CustomerServiceImpl
public class CustomerServiceImpl implements ICustomerService{
@Override
public void login() {
System.out.println("模拟顾客登录");
}
}
TestJDKProxy
public class TestJDKProxy {
@Test
public void test() {
ICustomerService customerServcie = new CustomerServiceImpl();
customerServcie.login();
}
@Test
public void test1() {
CustomerServiceImpl customerServcie = new CustomerServiceImpl();
ICustomerService proxy = (ICustomerService) Proxy.newProxyInstance(
customerServcie.getClass().getClassLoader(),
customerServcie.getClass().getInterfaces() ,
new InvocationHandler() {
@Override
public Object invoke(Object object, Method method, Object[] arg) throws Throwable {
System.out.println("记录时间前");
Object result = method.invoke(customerServcie, arg);
System.out.println("记录时间后");
return result;
}
});
proxy.login();
}
}
反编译
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* com.briup.aop.proxy.dproxy.jdk.ICustomerService
*/
package com.sun.proxy;
import com.briup.aop.proxy.dproxy.jdk.ICustomerService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0
extends Proxy
implements ICustomerService {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler invocationHandler) {
super(invocationHandler);
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("com.briup.aop.proxy.dproxy.jdk.ICustomerService").getMethod("login", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
return;
}
catch (NoSuchMethodException noSuchMethodException) {
throw new NoSuchMethodError(noSuchMethodException.getMessage());
}
catch (ClassNotFoundException classNotFoundException) {
throw new NoClassDefFoundError(classNotFoundException.getMessage());
}
}
public final boolean equals(Object object) {
try {
return (Boolean)this.h.invoke(this, m1, new Object[]{object});
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString() {
try {
return (String)this.h.invoke(this, m2, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode() {
try {
return (Integer)this.h.invoke(this, m0, null);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final void login() {
try {
this.h.invoke(this, m3, null);
return;
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
}
cglib
CGLIB通过ASM动态操作指令,生成了被代理类的子类,如果目标类是final修饰的,则不能够被代理
BookServiceImpl
public class BookServiceImpl {
public void findAll() {
System.out.println("查书");
}
}
TestCglib
public class TestCglib {
@Test
public void test() {
BookServiceImpl bookService = new BookServiceImpl();
bookService.findAll();
}
@Test
public void test2() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(BookServiceImpl.class);
// enhancer.setCallback(new MethodInterceptor() {
// @Override
// public Object intercept(Object object, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
// System.out.println(method.getName());
// System.out.println(methodProxy);
// System.out.println("查询时间前");
// Object result = methodProxy.invokeSuper(object, arg);
// System.out.println("查询时间后");
// return result;
// }
// });
BookServiceImpl bookService = new BookServiceImpl();
enhancer.setCallback(new InvocationHandler() {
@Override
public Object invoke(Object object, Method method, Object[] arg) throws Throwable {
System.out.println("查询时间前");
Object result = method.invoke(bookService, arg);
System.out.println("查询时间后");
return result;
}
});
BookServiceImpl proxy = (BookServiceImpl) enhancer.create();
proxy.findAll();
}
}
反编译
/*
* Decompiled with CFR.
*
* Could not load the following classes:
* com.briup.aop.proxy.dproxy.cglib.BookServiceImpl
*/
package com.briup.aop.proxy.dproxy.cglib;
import com.briup.aop.proxy.dproxy.cglib.BookServiceImpl;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Factory;
import org.springframework.cglib.proxy.InvocationHandler;
import org.springframework.cglib.proxy.UndeclaredThrowableException;
public class BookServiceImpl$$EnhancerByCGLIB$$b0c38b85
extends BookServiceImpl
implements Factory {
private boolean CGLIB$BOUND;
public static Object CGLIB$FACTORY_DATA;
private static final ThreadLocal CGLIB$THREAD_CALLBACKS;
private static final Callback[] CGLIB$STATIC_CALLBACKS;
private InvocationHandler CGLIB$CALLBACK_0;
private static Object CGLIB$CALLBACK_FILTER;
private static final Method CGLIB$findAll$0;
private static final Method CGLIB$equals$1;
private static final Method CGLIB$toString$2;
private static final Method CGLIB$hashCode$3;
private static final Method CGLIB$clone$4;
public BookServiceImpl$$EnhancerByCGLIB$$b0c38b85() {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85 bookServiceImpl$$EnhancerByCGLIB$$b0c38b85 = this;
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BIND_CALLBACKS(bookServiceImpl$$EnhancerByCGLIB$$b0c38b85);
}
static {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$STATICHOOK1();
}
public final boolean equals(Object object) {
try {
InvocationHandler invocationHandler = this.CGLIB$CALLBACK_0;
if (invocationHandler == null) {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BIND_CALLBACKS(this);
invocationHandler = this.CGLIB$CALLBACK_0;
}
return (Boolean)invocationHandler.invoke(this, CGLIB$equals$1, new Object[]{object});
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString() {
try {
InvocationHandler invocationHandler = this.CGLIB$CALLBACK_0;
if (invocationHandler == null) {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BIND_CALLBACKS(this);
invocationHandler = this.CGLIB$CALLBACK_0;
}
return (String)invocationHandler.invoke(this, CGLIB$toString$2, new Object[0]);
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode() {
try {
InvocationHandler invocationHandler = this.CGLIB$CALLBACK_0;
if (invocationHandler == null) {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BIND_CALLBACKS(this);
invocationHandler = this.CGLIB$CALLBACK_0;
}
return ((Number)invocationHandler.invoke(this, CGLIB$hashCode$3, new Object[0])).intValue();
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
protected final Object clone() throws CloneNotSupportedException {
try {
InvocationHandler invocationHandler = this.CGLIB$CALLBACK_0;
if (invocationHandler == null) {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BIND_CALLBACKS(this);
invocationHandler = this.CGLIB$CALLBACK_0;
}
return invocationHandler.invoke(this, CGLIB$clone$4, new Object[0]);
}
catch (CloneNotSupportedException | Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public Object newInstance(Callback[] callbackArray) {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85 bookServiceImpl$$EnhancerByCGLIB$$b0c38b85 = new BookServiceImpl$$EnhancerByCGLIB$$b0c38b85();
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$SET_THREAD_CALLBACKS(null);
return bookServiceImpl$$EnhancerByCGLIB$$b0c38b85;
}
public Object newInstance(Class[] classArray, Object[] objectArray, Callback[] callbackArray) {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85 bookServiceImpl$$EnhancerByCGLIB$$b0c38b85;
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$SET_THREAD_CALLBACKS(callbackArray);
Class[] classArray2 = classArray;
switch (classArray.length) {
case 0: {
bookServiceImpl$$EnhancerByCGLIB$$b0c38b85 = new BookServiceImpl$$EnhancerByCGLIB$$b0c38b85();
break;
}
default: {
throw new IllegalArgumentException("Constructor not found");
}
}
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$SET_THREAD_CALLBACKS(null);
return bookServiceImpl$$EnhancerByCGLIB$$b0c38b85;
}
public Object newInstance(Callback callback) {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$SET_THREAD_CALLBACKS(new Callback[]{callback});
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85 bookServiceImpl$$EnhancerByCGLIB$$b0c38b85 = new BookServiceImpl$$EnhancerByCGLIB$$b0c38b85();
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$SET_THREAD_CALLBACKS(null);
return bookServiceImpl$$EnhancerByCGLIB$$b0c38b85;
}
public final void findAll() {
try {
InvocationHandler invocationHandler = this.CGLIB$CALLBACK_0;
if (invocationHandler == null) {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BIND_CALLBACKS(this);
invocationHandler = this.CGLIB$CALLBACK_0;
}
Object object = invocationHandler.invoke(this, CGLIB$findAll$0, new Object[0]);
return;
}
catch (Error | RuntimeException throwable) {
throw throwable;
}
catch (Throwable throwable) {
throw new UndeclaredThrowableException(throwable);
}
}
public void setCallback(int n, Callback callback) {
switch (n) {
case 0: {
this.CGLIB$CALLBACK_0 = (InvocationHandler)callback;
break;
}
}
}
public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] callbackArray) {
CGLIB$THREAD_CALLBACKS.set(callbackArray);
}
public static void CGLIB$SET_STATIC_CALLBACKS(Callback[] callbackArray) {
CGLIB$STATIC_CALLBACKS = callbackArray;
}
public void setCallbacks(Callback[] callbackArray) {
Callback[] callbackArray2 = callbackArray;
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85 bookServiceImpl$$EnhancerByCGLIB$$b0c38b85 = this;
this.CGLIB$CALLBACK_0 = (InvocationHandler)callbackArray[0];
}
public Callback[] getCallbacks() {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BIND_CALLBACKS(this);
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85 bookServiceImpl$$EnhancerByCGLIB$$b0c38b85 = this;
return new Callback[]{this.CGLIB$CALLBACK_0};
}
public Callback getCallback(int n) {
InvocationHandler invocationHandler;
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BIND_CALLBACKS(this);
switch (n) {
case 0: {
invocationHandler = this.CGLIB$CALLBACK_0;
break;
}
default: {
invocationHandler = null;
}
}
return invocationHandler;
}
static void CGLIB$STATICHOOK1() {
CGLIB$THREAD_CALLBACKS = new ThreadLocal();
CGLIB$findAll$0 = Class.forName("com.briup.aop.proxy.dproxy.cglib.BookServiceImpl").getDeclaredMethod("findAll", new Class[0]);
CGLIB$equals$1 = Class.forName("java.lang.Object").getDeclaredMethod("equals", Class.forName("java.lang.Object"));
CGLIB$toString$2 = Class.forName("java.lang.Object").getDeclaredMethod("toString", new Class[0]);
CGLIB$hashCode$3 = Class.forName("java.lang.Object").getDeclaredMethod("hashCode", new Class[0]);
CGLIB$clone$4 = Class.forName("java.lang.Object").getDeclaredMethod("clone", new Class[0]);
}
private static final void CGLIB$BIND_CALLBACKS(Object object) {
block2: {
Object object2;
block3: {
BookServiceImpl$$EnhancerByCGLIB$$b0c38b85 bookServiceImpl$$EnhancerByCGLIB$$b0c38b85 = (BookServiceImpl$$EnhancerByCGLIB$$b0c38b85)object;
if (bookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BOUND) break block2;
bookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$BOUND = true;
object2 = CGLIB$THREAD_CALLBACKS.get();
if (object2 != null) break block3;
object2 = CGLIB$STATIC_CALLBACKS;
if (CGLIB$STATIC_CALLBACKS == null) break block2;
}
bookServiceImpl$$EnhancerByCGLIB$$b0c38b85.CGLIB$CALLBACK_0 = (InvocationHandler)((Callback[])object2)[0];
}
}
}
spring集成代理
未增强前
ICategoryService
public interface ICategoryService {
void findAll();
}
CategoryServiceImpl
public class CategoryServiceImpl implements ICategoryService{
@Override
public void findAll() {
System.out.println("模拟 查询所有目录");
}
}
bean.xml
<bean id = "categoryService" class="com.briup.aop.demo.service.impl.CategoryServiceImpl"></bean>
TestAop
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class TestAop {
@Autowired
private ICategoryService categoryService;
@Test
public void test() {
//categoryService.findAll();
categoryService.insert();
}
}
后置处理器
MyBeanPostProcessor 生命周期的一环
public class MyBeanPostProcessor implements BeanPostProcessor{
private LogUtil logUtil;
public void setLogUtil(LogUtil logUtil) {
this.logUtil = logUtil;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if("categoryService".equals(beanName)) {
// System.out.println(bean);
// System.out.println(beanName);
return Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("hello");
Object result = method.invoke(bean, args);
System.out.println("world");
return result;
}
});
}
return bean;
}
}
bean.xml
<bean id = "myPostProcessor" class="com.briup.aop.demo.life.MyBeanPostProcessor"></bean>
日志改造 LogUtil
public class LogUtil {
public void before() {
System.out.println("执行前");
}
public void after() {
System.out.println("执行后");
}
}
public class MyBeanPostProcessor implements BeanPostProcessor{
private LogUtil logUtil;
public void setLogUtil(LogUtil logUtil) {
this.logUtil = logUtil;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.startsWith("user")) {
// System.out.println(bean);
// System.out.println(beanName);
return Proxy.newProxyInstance(
bean.getClass().getClassLoader(),
bean.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// System.out.println("hello");
logUtil.before();
Object result = method.invoke(bean, args);
logUtil.after();
// System.out.println("world");
return result;
}
});
}
return bean;
}
}
bean.xml
<bean id = "logUtil" class="com.briup.aop.demo.aspect.LogUtil"/>
<bean id = "myPostProcessor" class="com.briup.aop.demo.life.MyBeanPostProcessor">
<property name="logUtil" ref="logUtil"/>
</bean>
aop
此处需要导入aspectjweaver-1.9.4.jar
AOP就是面向切面编程,是一种非常适合在无须修改业务代码的前提下,对某个或某些业务增加同一的功能,比如日志记录,权限控制,事务管理等,能很好的使得代码解耦,提高开发效率。
- advice 通知,建议。
- 在Spring中通过定义Advice来定义代理逻辑
- pointcut 切入点
- 表示Advice对应的代理逻辑应用在哪个类,哪个方法上
- advisor advice + pontcut
- 表示代理逻辑和切点的一个整体,可通过定义或封装一个Advisor,来定义切点和代理逻辑
- weaving 织入
- 将Advice代理逻辑在源代码级别嵌入到切点的过程,叫做织入
- target 目标对象
- 被代理对象,在aop生成的代理对象中会持有目标对象
- join point 连接点
- 在Spring Aop中就是方法的执行点
AOP的工作原理
AOP是发生在Bean的生命周期过程中
- Spring生成Bean对象时,先实例化出来一个对象,也就是target对象
- 再对target对象进行属性填充
- 再初始化后步骤中,会判断target对象有没有对应的切面
- 如果有切面,就表示当前target对象需要进行AOP
- 通过Cglib或JDK动态代理机制生成一个代理对象,作为最终的bean对象
bean.xml
<aop:config>
<aop:pointcut expression="execution(* com.briup.aop.demo.service..*.*(..))" id="myPoint"/>
<aop:aspect ref="logUtil">
<aop:before method="before" pointcut-ref="myPoint"/>
<aop:after method="after" pointcut-ref="myPoint"/>
</aop:aspect>
</aop:config>
事务
导入jar
- spring-tx-5.0.2.RELEASE.jar
- spring-jdbc-5.0.2.RELEASE.jar
- druid-1.1.10.jar
- mysql-connector-java-5.1.7-bin.jar
编程式事务
使用编程的方式,自己去实现事务管理工作,例如事务的开启、提交、回滚操作,需要开发人员自己调用commit()或者rollback()等方法来实现。 编程式事务需要我们自己在逻辑代码中手动书写事务控制逻辑,所以编程式事务是具有侵入性的。 我们之前的代码中,对事务进行提交或者回滚的操作,就属于编程式事务。
CategoryDaoImpl
public class CategoryDaoImpl implements CategoryDao{
private JdbcTemplate JdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
JdbcTemplate = jdbcTemplate;
}
@Override
public void insert() {
String sql = "insert into es_category(name,description) values('vanse','hello')";
JdbcTemplate.update(sql);
}
}
CategoryServiceImpl
public class CategoryServiceImpl implements ICategoryService{
private CategoryDao categoryDao;
private PlatformTransactionManager transactionManager;
@Override
public void findAll() {
System.out.println("模拟 查询所有目录");
}
@Override
public void insert() {
TransactionDefinition definition = new DefaultTransactionDefinition();;
TransactionStatus status = transactionManager.getTransaction(definition);
try {
System.out.println("模拟 插入數據");
categoryDao.insert();
int i = 1/0;
transactionManager.commit(status);
} catch (TransactionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
transactionManager.rollback(status);
}
}
public void setCategoryDao(CategoryDao categoryDao) {
this.categoryDao = categoryDao;
}
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
}
bean.xml
<bean id = "dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///estore-nongda2018"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id = "jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="categoryDao" class="com.briup.aop.demo.dao.CategoryDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<bean id = "transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id = "categoryService" class="com.briup.aop.demo.service.impl.CategoryServiceImpl">
<property name="categoryDao" ref="categoryDao"></property>
<property name="transactionManager" ref="transactionManager"></property>
</bean>
声明式事务
只需要声明或者配置一个事务就可以了,不需要我们手动去编写事务管理代码。 这种方式属于非侵入性的,可以使用AOP思想实现事务管理,能够提高代码的复用性,提高开发效率。
在Spring中,使用AOP来实现事务操作
- 将service层事务的开启、提交、回滚等代码抽出来,封装成切面类
- 使用环绕通知,将事务管理的代码织入到service层需要事务支持的方法中
- 获取service 实现类的代理对象,调用方法时会动态加入事务管理的代码
<!-- aop声明式事务
执行commit 逻辑 回滚rollbalck (环绕通知) -->
<!-- 事务用advisor -->
<!-- 配置事务 拦截器 -->
<tx:advice transaction-manager="transactionManger" id="txAdvice">
<!-- TransactionDefiniton -->
<tx:attributes>
<tx:method name="insert*" rollback-for="Excetion" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 增强(事务) 目标类 -->
<aop:pointcut expression="execution(* com.briup.springaop.servcie..*.*(..))" id="cut"/>
<!-- adviosor和adivce和aspect -->
<!-- adviosor == advice+pointcut -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="cut"/>
</aop:config>
总配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- <bean id="categoryService"
class="com.briup.springaop.CategoryServiceImpl"></bean>
自定义后置处理器
<bean id="myPostProcessor"
class="com.briup.springaop.MyPostProcessor">
<property name="logUtil" ref="logUtil"></property>
</bean>
<bean id = "logUtil" class = "com.briup.springaop.LogUtil"></bean> -->
<!-- 底层做了动态代理 后置处理器检测到该类使用的代理 -->
<!-- dom4j解析 xml aop: -->
<!-- <aop:config>
增强逻辑 目标类
切入点 目标类 一串
<aop:pointcut expression="execution(* com.briup.springaop..*.*(..))" id="myPoint"/>
增强逻辑
切面类
<aop:aspect ref="logUtil">
<aop:before method="before" pointcut-ref="myPoint"/>
<aop:after method="after" pointcut-ref="myPoint"/>
拦截器 around 环绕通知 需要aop联盟的包
<aop:around method="around" pointcut-ref="myPoint"/>
</aop:aspect>
</aop:config> -->
<!-- service -->
<bean id = "categoryService" class="com.briup.springaop.servcie.CategoryServiceImpl">
<property name="categoryDao" ref="categoryDao"></property>
<!-- <property name="transactionManger" ref="transactionManger"></property> -->
</bean>
<bean id= "transactionManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- dao -->
<bean id = "categoryDao" class="com.briup.springaop.dao.CategoryDaoImpl" >
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
<!-- jdbcTemplate -->
<bean id = "jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- dataSource -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///estore-nongda2018"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- aop声明式事务
执行commit 逻辑 回滚rollbalck (环绕通知) -->
<!-- 事务用advisor -->
<!-- 配置事务 拦截器 -->
<tx:advice transaction-manager="transactionManger" id="txAdvice">
<!-- TransactionDefiniton -->
<tx:attributes>
<tx:method name="insert*" rollback-for="Excetion" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 增强(事务) 目标类 -->
<aop:pointcut expression="execution(* com.briup.springaop.servcie..*.*(..))" id="cut"/>
<!-- adviosor和adivce和aspect -->
<!-- adviosor == advice+pointcut -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="cut"/>
</aop:config>
</beans>