cglib动态代理
(1)pom中添加依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
(2)
UserDao.class
public class UserDao{
public void add() {
System.out.println("UserDao.add([])方法");
}
}
(3)MyMethodInterceptor.class
package com.tjetc.proxy;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyMethodInterceptor implements MethodInterceptor {
/**
*
* @param proxy 代理对象(子类对象)
* @param method 被调用的方法
* @param args 方法的参数数组
* @param methodProxy method增强,好处:可以提高性能
* @return 返回值
* @throws Throwable
*/
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//前置增强
System.out.println("开启事务");
//调用目标类的方法
Object result = methodProxy.invokeSuper(proxy, args);
//后置增强
System.out.println("提交事务");
return result;
}
}
(4)
package com.tjetc.test;
import com.tjetc.dao.impl.UserDaoImpl;
import com.tjetc.proxy.MyMethodInterceptor;
import net.sf.cglib.proxy.Enhancer;
import org.junit.Test;
public class TestCglibProxy {
@Test
public void testAdd(){
//创建目标类对象
Object obj = new UserDao();
//创建Enhancer对象
Enhancer enhancer = new Enhancer();
//设置被代理的父类对象类类型
enhancer.setSuperclass(obj.getClass());
//设置enhancer对象的属性中间类方法拦截器
enhancer.setCallback(new MyMethodInterceptor());
//调用enhancer的create()方法使用字节码技术动态在内存中创建目标类的子类(代理类)对象
UserDaoImpl proxy = (UserDaoImpl) enhancer.create();
//调用代理类对象的方法
proxy.add();;
}
}
SpringAOP基于XML实现
(1)
导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
(2)
创建applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
">
</beans>
(3)
package com.tjetc.aspect;
//切面类
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class TransactionAspect {
public void doBefore(JoinPoint jp){
System.out.println("前置增强");
System.out.println("jp.getTarget() = " + jp.getTarget());
System.out.println("jp.getArgs() = " + jp.getArgs());
System.out.println("jp.getSignature() = " + jp.getSignature());
}
public void doAfterReturning(){
System.out.println("后置增强");
}
public void doAfter(){
System.out.println("最终增强");
}
public void doAfterThrowing(){
System.out.println("异常增强");
}
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕前");
Object result = pjp.proceed();
System.out.println("环绕后");
return result;
}
}
(4)
package com.tjetc.service;
//被代理的目标类
public class PersonService {
public void add(){
System.out.println("PersonService.add([])方法");
}
}
(5)在applicationContext.xml下配置bean节点和切面
<!--被代理的目标类-->
<bean id="personService" class="com.tjetc.service.PersonService"></bean>
<!--切面类-->
<bean id="transactionAspect" class="com.tjetc.aspect.TransactionAspect"></bean>
<!--配置切面-->
<aop:config>
<!--配置在外面的切点,所有切面共享;配置在某个切面内的切点,该切点独享-->
<!--配置切面-->
<aop:aspect id="myAspect" ref="transactionAspect">
<!--配置切点-->
<aop:pointcut id="myCut" expression="execution(* com.tjetc.service..*.*(..))"></aop:pointcut>
<!--配置增强:两种模式,一种是前4个;一种是最后一个-->
<aop:before method="doBefore" pointcut-ref="myCut"></aop:before>
<aop:after-returning method="doAfterReturning" pointcut-ref="myCut"></aop:after-returning>
<aop:after method="doAfter" pointcut-ref="myCut"></aop:after>
<aop:after-throwing method="doAfterThrowing" pointcut-ref="myCut"></aop:after-throwing>
<aop:around method="doAround" pointcut-ref="myCut"></aop:around>
</aop:aspect>
</aop:config>
(6)
package com.tjetc.test;
import com.tjetc.service.PersonService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
@Test
public void testAdd(){
//实例化容器对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//得到代理对象
PersonService personService = (PersonService) context.getBean("personService");
System.out.println("personService.getClass() = " + personService.getClass());
//调用代理对象的方法
personService.add();
}
}
日志
----------------日志----------------
(1)在pom.xml文件中加入以下依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
(2)applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
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
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">
</beans>
(3)PersonService.java
package com.tjetc.service;
public class PersonService {
public void add(){
System.out.println("PersonService.add([])方法");
}
public void update(){
System.out.println("PersonService.update([])方法");
}
}
(4)log4j.properties
#设置级别和目的地(这里可以设置多个目的地)
log4j.rootLogger=DEBUG,Console,File
#Console 输出到控制台
log4j.appender.Console=org.apache.log4j.ConsoleAppender
#灵活设置日志格式
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
#日志输出格式
# %d=datetime日期和时间
# %t=thread
# %-5p -表示左对齐 5代表5个字符 p代表级别
# %c 表示class 哪个类
# %m message
# %n 换行\n的意思
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#输出到文件(一直输出到该文件中)
log4j.appender.File = org.apache.log4j.FileAppender
#输出日志文件路径
log4j.appender.File.File = D:\\log\\JavaBean_log\\File.log
#包含日志产生的时间、线程、类别等等信息 #TTCC T Time Thread C class
log4j.appender.File.layout = org.apache.log4j.TTCCLayout
#日志文件输出格式
log4j.appender.File.layout.ConversionPattern =%d [%t] %-5p [%c] - %m%n
(5)测试类 TestLog4j
package com.tjetc.test;
import org.apache.log4j.Logger;
public class TestLog4j {
//声明日志对象
public static Logger logger = Logger.getLogger(TestLog4j.class);
public static void main(String[] args) {
//日志的级别从低到高
//很低的日志级别一般不会使用
logger.trace("这是trace日志信息");
//细粒度信息对调试应用非常有帮助,主要打印一些运行信息
logger.debug("这是debug的日志");
//粗粒度突出强调应用程序的运行过程,打印感兴趣或者重要的信息
logger.info("这是info日志信息");
//表明会出现潜在错误的情形,有些信息不是错误信息,但也要给程序要一点提示
logger.warn("这是warn日志信息");
//指出虽然发生错误,但不影响运行,打印错误和异常信息,如果不想输出太多日志可以使用该级别
logger.error("这是error日志信息");
//每个严重的错误事件将会导致应用程序的退出,出现错误可以停止程序运行进行调试
logger.fatal("这是fatal日志信息");
}
}
(6)制造一个bug
在PersonService的add方法中添加System.out.println(1/0);
public void add(){
System.out.println("PersonService.add([])方法");
System.out.println(1/0);
}
(7)
package com.tjetc.aspect;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
public class LogAspect {
private static Logger logger = Logger.getLogger(LogAspect.class);
public void doBefore(JoinPoint jp){
logger.info("方法:"+jp.getSignature()+",进入时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));
}
public void doAfterReturning(JoinPoint jp){
logger.info("方法:"+jp.getSignature()+",方法返回时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));
}
public void doAfter(JoinPoint jp){
logger.info("方法:"+jp.getSignature()+",方法最终离开时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));
}
public void doAfterThrowing(JoinPoint jp,Exception ex){
logger.info("方法:"+jp.getSignature()+",方法发生异常时间:"+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(new Date()));
//在日志记录发生什么异常的详情
StringWriter stringWriter = new StringWriter();
//将异常的详细信息写到StringWriter缓存
ex.printStackTrace(new PrintWriter(stringWriter,true));
//将StringWriter缓存的日志信息写到日志文件中去
logger.info(stringWriter.getBuffer().toString());
}
}
(8)applicationContext中配置节点 切面 切点
<bean id="personService" class="com.tjetc.service.PersonService"></bean>
<!--切面类-->
<bean id="logAspect" class="com.tjetc.aspect.LogAspect"></bean>
<!--aop配置-->
<aop:config>
<!--配置切面-->
<aop:aspect id="logAspect" ref="logAspect">
<!--配置切点-->
<aop:pointcut id="mycut" expression="execution(* com.tjetc.service..*.*(..))"></aop:pointcut>
<!--配置增强-->
<aop:before method="doBefore" pointcut-ref="mycut"></aop:before>
<aop:after-returning method="doAfterReturning" pointcut-ref="mycut"></aop:after-returning>
<aop:after method="doAfter" pointcut-ref="mycut"/>
<aop:after-throwing method="doAfterThrowing" throwing="ex" pointcut-ref="mycut"></aop:after-throwing>
</aop:aspect>
</aop:config>
(9)测试类TestAopLog
package com.tjetc.test;
import com.tjetc.service.PersonService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAopLog {
@Test
public void testAdd(){
//创建容器对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//从容器得到代理对象
PersonService personService = (PersonService) context.getBean("personService");
//调用方法
personService.add();
personService.update();
}
}
自动生成
(0)settings-editor-Live Templates-点"+"-Live Template
(1)引入依赖
<dependencies>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<verbose>true</verbose>
<overwrite>false</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
(2)File and Code Templates
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/spring0712" userId="root"
password="123456">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.tjetc.domain"
targetProject=".\src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.tjetc.mapper"
targetProject=".\src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.tjetc.mapper"
targetProject=".\src\main\java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
<!-- 指定数据库表 -->
<!--<table schema="" tableName="t_user">
<!– 取消表名_之前的前缀 –>
<domainObjectRenamingRule searchString="^[^_]" replaceString="" />
<domainObjectRenamingRule searchString="^t_" replaceString="" />
<!– 取消表字段_之前的前缀 –>
<columnRenamingRule searchString="^[^_]+" replaceString=""/>
</table>-->
<table schema="" tableName="person">
</table>
</context>
</generatorConfiguration>
(3)
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
public class GeneratorSqlMap {
public void generator() throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//指定 逆向工程配置文件
File configFile = new File("generatorConfig.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
callback, warnings);
myBatisGenerator.generate(null);
}
public static void main(String[] args) throws Exception {
try {
GeneratorSqlMap generatorSqlmap = new GeneratorSqlMap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(4)点击右侧的Maven–mybatis-generator
然后点击mybatis-generator:generate
Spring&Mybatis整合
(1)在pom.xml文件中导入依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.3.4</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.23</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
(2)配置applicationContext.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:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
">
<!--配置扫描的基本包-->
<context:component-scan base-package="com.tjetc"></context:component-scan>
<!--加载属性文件-->
<context:property-placeholder location="classpath*:db.properties"></context:property-placeholder>
<!--配置数据源数据库连接池-->
<bean id="DataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="DataSource"></property>
</bean>
<!--配置SqlSessionBean-->
<bean id="SqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="DataSource"></property>
<property name="configLocation" value="classpath:mybatis.xml"></property>
</bean>
<!--配置mybatis扫描mapper接口的基本包-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="beanName" value="sqlSession"></property>
<property name="basePackage" value="com.tjetc.mapper"></property>
</bean>
<!--以下配置事务-->
<aop:config>
<!--切点-->
<aop:pointcut id="txCut" expression="execution(* com.tjetc.service..*.*(..))"></aop:pointcut>
<!--advisor 切点和事务增强器的桥梁-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txCut"></aop:advisor>
</aop:config>
<!--配置事物的增强-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<!--never从来没有事务 not_supported不支持事务 mandatory强制事务 required需要事务 -->
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
(3)配置mybatis.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<package name="com.tjetc.domain"/>
</typeAliases>
</configuration>
(4)把自动生成的com包复制过来
然后创建service接口和实现类
package com.tjetc.service;
import com.tjetc.domain.Person;
public interface PersonService {
void add(Person person);
}
(5) 实现类
package com.tjetc.service.impl;
import com.tjetc.domain.Person;
import com.tjetc.mapper.PersonMapper;
import com.tjetc.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PersonServiceImpl implements PersonService {
@Autowired
private PersonMapper personMapper;
public void add(Person person) {
personMapper.insert(person);
}
}
(6)测试类
package com.tjetc.test;
import com.tjetc.domain.Person;
import com.tjetc.service.PersonService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test1 {
@Test
public void testAdd(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
PersonService personServiceImpl = (PersonService) context.getBean("personServiceImpl");
Person person = new Person();
person.setName("zs");
person.setAge(20);
personServiceImpl.add(person);
}
}