spring 动态代理,静态代理,AOP,IOC,事务管理

Spring框架

1.基本使用

1.1添加依赖

   <!-- Spring常用依赖 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>

1.2创建配置文件

1.文件命名规则:命名无限制,约定俗成命名有:spring-context.xml、applicationContext.xml、beans.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>:JavaBean
            id:bean的唯一标识
            class:bean全类名
    -->
    <bean id="userServiceImpl" class="com.lqq.serviceImpl.UserServiceImpl"></bean>
</beans>

1.3测试

1.首先实例化工厂
2.通过工厂实例化对象
3.通过对象调用方法

  @Test
    public void test1(){
        //1.实例化工厂
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:beans.xml");
        //2.通过工厂获得实例
        //UserServiceImpl userServiceImpl = (UserServiceImpl) ctx.getBean("userServiceImpl");
        //不需要强转的实例
        UserServiceImpl userServiceImpl = ctx.getBean("userServiceImpl", UserServiceImpl.class);
        userServiceImpl.say();

    }

2.spring核心思想控制反转IOC

将对象的创建权限转交给spring容器,spring容器为我们创建对象,我们只需要从spring容器中获取实例

3.依赖注入DI

3.1声明的依赖注入

1.在某个Bean中需要实例另一个Bean对象,需要进行依赖注入

public class UserServiceImpl {
    //private UserDaoImpl userDao = new UserDaoImpl();
    private UserDaoImpl userDao;// 只要声明了对象spring容器会自动创建实例

    public void setUserDao(UserDaoImpl userDao) {
        this.userDao = userDao;
    }

    public void addUser(){
        System.out.println("UserServiceImpl.addUser");
        userDao.addUser();
    }
}

 <bean id="userService" class="com.lqq.service.impl.UserServiceImpl">
        <!--
        依赖注入:给userService中的userDao属性赋值
        把userDao实例注入到UserService中的userDao属性中,使用set方法
        -->
        <property name="userDao" ref="userDao"></property>
    </bean>
    <bean id="userDao" class="com.lqq.dao.impl.UserDaoImpl"></bean>

3.2一个实例不同数据类型的依赖注入

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    public User(Integer id,String name){
        this.id = id;
        this.name = name;
    }
    private Integer id;
    private String name;
    private List<String> email;
    private Set<String> sets;
    private Map<String,Object> map;
    private String[] arrays;
    private Properties properties;


}


 <bean id="user" class="com.lqq.entity.User">
        <property name="id" value="1"/>
        <property name="name" value="鲁千旗"/>
        <property name="email" >
            <list>
                <value>lqq1.com</value>
                <value>lqq2.com</value>
                <value>lqq3.com</value>
            </list>
        </property>
        <property name="sets">
            <set>
                <value>A</value>
                <value>B</value>
                <value>C</value>
            </set>
        </property>
        <property name="map">
            <map>
                <entry key="lqq" value="鲁千旗"></entry>
                <entry key="lqq" value="鲁千旗"></entry>
                <entry key="lqq" value="鲁千旗"></entry>
                <entry key="userDao" value-ref="userDao"></entry>
            </map>
        </property>
        <property name="arrays">
            <array>
                <value>1</value>
                <value>1</value>
                <value>1</value>
            </array>
        </property>
        <property name="properties">
            <props>
                <prop key="lqq1">lqq1</prop>
                <prop key="lqq2">lqq2</prop>
                <prop key="lqq3">lqq3</prop>
            </props>
        </property>
    </bean>

3.3spring容器创建对象通过的默认是无参构造方法

通过有参构造方法完成spring容器的对象创建

  <bean id="user2" class="com.lqq.entity.User">
        <!--
        type:根据类型的寻找参数
        name:根据构造器形参名寻找
        index:根据索引
        ref:根据对象
        value:文本值
        -->
    <!--    <constructor-arg name="id" value="10"/>
        <constructor-arg name="name" value="lqq"/>-->
        <!--<constructor-arg index="0" value="10"/>
        <constructor-arg index="1" value="lqq"/>-->
        <constructor-arg type="java.lang.Integer" value="10"/>
        <constructor-arg type="java.lang.String" value="lqq"/>
    </bean>

3.4自动注入autowire

   <!--
            <bean>:JavaBean
            id:bean的唯一标识
            class:bean全类名
            autowire:自动注入
                    no:默认关闭
                    byName:根据名称注入,已被注入属性的名称为准到spring							容器中找,找到注入,找不到不注入
                    default:根据父标签自动注入
    -->
    <bean id="userService" class="com.lqq.service.impl.UserServiceImpl" autowire="byName">
       
        <!--<property name="userDao" ref="userDao"></property>-->
    </bean>

4.spring容器创建的实例默认是单例的

 <!--
   Spring默认创建bean是单例的
   scope:控制bean是否单例的
         singleton:单例默认的
         prototype:原生多例的
         request:每次请求创建一个bean
         session:每个session创建一个bean
   -->
   <bean id="userService" class="com.lqq.service.impl.UserServiceImpl" scope="prototype"></bean>

5.spring生命周期

  <!--
   容器创建初始化时调用的方法init-method
   销毁容器时调用的方法destroy-method
   -->
   <bean id="userDao" class="com.lqq.dao.impl.UserDaoImpl" init-method="init" destroy-method="destory"></bean>

单例bean:
	随着工厂启动创建==》构造方法==》set方法依赖注入==》init容器初始化方法==》构建完成==》工厂关闭销毁

6.代理设计模式

6.1静态代理

使用静态代理完成,真实事务与系统服务的分离

6.1.1代理类

ublic class UserServiceImplProxy implements UserService {
    private LogManager logManager;
    private TransactionManager transactionManager;
    private UserService userService;
    public UserServiceImplProxy(UserService userService,TransactionManager transactionManager,LogManager logManager){
        this.userService = userService;
        this.logManager = logManager;
        this.transactionManager = transactionManager;
    }
    @Override
    public void addUser() {
        logManager.start();
        transactionManager.start();
        userService.addUser();
        transactionManager.commit();
        logManager.end();
    }
}

6.1.2真实事务类

public class UserServiceImpl implements UserService {

    //真是业务主体
    @Override
   public void addUser(){
       System.out.println("真实业务主体");
   }
}

6.1.3测试效果

public void testAddUserProxy(){
        //1.创建系统服务对象
        TransactionManager transactionManager = new TransactionManager();
        LogManager logManager = new LogManager();
        //2.创建真实事务对象
        UserService userService = new UserServiceImpl();
        //3.创建代理类
        UserServiceImplProxy userServiceImplProxy = new UserServiceImplProxy(userService, transactionManager, logManager);
       //4.调用方法
        userServiceImplProxy.addUser();
    }

6.2基于jdk动态代理

由于静态代理每一个真实事务类都需要一个单独的代理所以,我们需要一个公共的代理,通过接口完成动态代理,真实业务必须继承接口

6.2.1创建一个公共的代理类ProxyHandler

public class ProxyHanlder implements InvocationHandler {
    //系统服务
    private LogManager logManager;
    private TransactionManager transactionManager;
    private Object target;//这是业务主体
    public ProxyHanlder(TransactionManager transactionManager,LogManager logManager,Object object){
        this.logManager = logManager;
        this.transactionManager = transactionManager;
        this.target = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //1.系统服务开始
        logManager.start();
        transactionManager.start();
        //2.真实业务主体
        Object invoke = method.invoke(target, args);
        //3.系统服务收尾
        transactionManager.commit();
        logManager.end();
        return invoke;
    }
}

6.2.3测试

  public void testAddTeacherProxy(){
        //1.创建系统服务对象
        TransactionManager transactionManager = new TransactionManager();
        LogManager logManager = new LogManager();
        //2.创建真实事务对象
        TeacherService teacherService = new TeacherServiceImpl();
        //3.创建代理类
        ClassLoader classLoader = teacherService.getClass().getClassLoader();//真实事务对象的类加载器
        Class<?>[] interfaces = teacherService.getClass().getInterfaces();//这是事务的接口
        ProxyHanlder proxyHanlder = new ProxyHanlder(transactionManager, logManager, teacherService);//自定义handler
        //4.创建代理对象
        TeacherService o = (TeacherService) Proxy.newProxyInstance(classLoader, interfaces, proxyHanlder);
        //5.调用
        o.addTeacher();
    }

6.3基于CGlib的动态代理

通过父子关系完成动态代理,真实业务类不需要继承接口

6.3.1创建公共代理类

public class CglibProxyHandler implements InvocationHandler {
    private TransactionManager transactionManager;
    private LogManager logManager;
    private Object target;
    public CglibProxyHandler(TransactionManager transactionManager,LogManager logManager,Object target){
        this.logManager = logManager;
        this.transactionManager =transactionManager;
        this.target = target;
    }
    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        logManager.start();
        transactionManager.start();
        Object invoke = method.invoke(target, objects);
        transactionManager.commit();
        logManager.end();
        return invoke;
    }
}

6.3.2测试

 public void testCglibProxy(){
        //1.创建系统服务对象
        TransactionManager transactionManager = new TransactionManager();
        LogManager logManager = new LogManager();
        //2.创建真实事务对象
        UserServiceImpl userService = new UserServiceImpl();
        //3.创建代理类
        Enhancer enhancer = new Enhancer();
        //为代理类设置父类
        enhancer.setSuperclass(UserServiceImpl.class);
        //设置自定义的handler,目的是调用系统服务代码
        enhancer.setCallback(new CglibProxyHandler(transactionManager,logManager,userService));
        //生成代理类对象
        UserServiceImpl o = (UserServiceImpl) enhancer.create();
            o.addUser();
        System.out.println(o.getClass());
    }

7.Aop面向切面编程

7.1环境搭建

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.1.6.RELEASE</version>
</dependency>

7.2AOP中的术语

7.2.1目标对象

就是真实事务主体

7.2.2增强(通知)

系统服务:前置通知:MethodBeforeAdvice
		后置通知:AfterReturningAdvice
		环绕通知:MethodInterceptor
		异常抛出通知:ThrowsAdvice

前置通知

public class MyBeforeAdvices implements MethodBeforeAdvice {
    /**
     * 目标对象的目标方法之前调用
     * @param method 目标方法
     * @param objects 目标方法的参数
     * @param o 目标对象
     * @throws Throwable
     */
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("方法调用之前");
    }
}

后置通知

public class MyBeforeAdvices implements AfterReturningAdvice {
    /**
     * 目标对象的目标方法之前调用
     * @param method 目标方法
     * @param objects 目标方法的参数
     * @param o 目标对象
     * @throws Throwable
     */
@Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("方法调用之后");
    }
}

环绕通知

public class MyMethodInterceptor  implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("环绕开始");
        Object proceed = methodInvocation.proceed();
        System.out.println("环绕结束");
        return proceed;
    }
}

异常抛出

public class MyThrowAdvice implements ThrowsAdvice {
    public void afterThrowing(Method method, Object[] args, Object target, Exception e) throws Throwable {
        System.out.println("method=" + method.getName());
        System.out.println("抛出异常:" + e.getMessage());
        System.out.println("成功回滚事务");
    }
}

bean.xml配置

   <bean id="userService" class="com.lqq.service.impl.UserServiceImpl"/>
    <bean id="myBeforeAdvices" class="com.lqq.advices.MyBeforeAdvices"/>
    <bean id="myMethodInterceptor" class="com.lqq.advices.MyMethodInterceptor"/>
    <bean id="myMyThrowAdvic" class="com.lqq.advices.MyThrowAdvice"/>
    <aop:config>
        <!--
         只有目标方法能匹配到当前表达式才会创建代理
        -->
        <!--
        1.先匹配表达式
        2.通过表达式的id找到对应的advice
        3.通过advice调用增强的方法
        -->
        <aop:pointcut id="p1" expression="execution(* com.lqq.service.UserService.*(..))"/>
        <aop:advisor advice-ref="myMethodInterceptor" pointcut-ref="p1"/>
        <aop:advisor advice-ref="myMyThrowAdvic" pointcut-ref="p1"/>
    </aop:config>

7.2.3连接点

能添加通知的地方

7.2.4切点

真正添加通知的地方

7.2.5织入

将通知和方法添加到代理类中的过程

7.2.6切面

控制通知(增强)的控制范围

8.数据源引入

8.1DaoImpl实现类需要的配置

8.1.1添加依赖

  <!--添加JdbcTemplate依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>

8.1.2实现dao层的方法

//继承jdbcTempalte不能直接使用,必须要注入数据源
public class AccountDaoImpl  extends JdbcTemplate implements AccountDao {
    @Override
    public void inMoney(String inName, Double money) {
       super.update("update t_account set money = money + ? where name=?",money,inName);
    }

    @Override
    public void outMoney(String outName, Double money) {
        super.update("update t_account set money = money - ? where name=?",money,outName);
    }
}

8.1.3引入数据库连接池和数据库依赖

<dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>

8.1.4创建数据源

<!--创建数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" >
    <property name="driverClassName" value="${jdbc.driverClass}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

8.1.5引入jdbc属性配置文件

 <!--加载属性文件jdbc.xml-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

8.1.6daoImpl需要操作数据库所以需要进行属性注入

 <!--继承jdbcTempalte不能直接使用,必须要注入数据源-->
    <bean id="accountDao" class="com.lqq.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

9.TransactionManager事务管理器

9.1ServiceImpl完成事务管理需要进行的配置

9.1.1添加事务依赖

 <!--添加事务相关的依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.1.6.RELEASE</version>
    </dependency>

9.1.2创建事务管理器

 <!--定义一个事务管理器,负责事物的提交或者回滚-->
    <bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

9.1.3创建一个事务策略

 <!--事务的策略
    id:唯一标识
    transaction-manager:事务管理器
    -->
    <tx:advice id="txAdvices" transaction-manager="tx">
        <!--具体事务属性
        name:方法名称,支持通配符
        isolation:事务隔离级别
        propagation:事务传播属性
        read-only:是否只读
        -->
        <tx:attributes>
            <tx:method name="t*" isolation="DEFAULT" read-only="false" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

9.1.4利用aop完成事务策略的引入

 <aop:config>
        <aop:pointcut id="p1" expression="execution(* com.lqq.service.AccountService.*(..))"/>
        <aop:advisor advice-ref="myAfterAdvice" pointcut-ref="p1"/>
        <aop:advisor advice-ref="txAdvices" pointcut-ref="p1"/>
    </aop:config>

1.创建一个事务管理器
2.创建事务管理策略绑定事务管理器
3.利用aop完成事务管理策略的使用
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值