3.Spring-DI

一.Bean元素的继承

BaseDAO公共的DAO

@ToString
public abstract class BaseDAO {
	//模拟一个连接池
	@Setter
	protected String dataSource;
}

DepartmentDAOImpl类

@Setter
public class DepartmentDAOImpl extends BaseDAO{

	@Override
	public String toString() {
		super.toString();
		return "DepartmentDAO ["+dataSource+"]";
	}
	
}

EmployeeDAOImpl

@Setter
public class EmployeeDAOImpl extends BaseDAO{

	@Override
	public String toString() {
		super.toString();
		return "EmployeeDAOImpl ["+dataSource+"]";
	}
	
}

App-context.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 id="baseDAO" abstract="true" class="cn.dusk._1_extends.BaseDAO">
    	<property name="dataSource" value="druid"/>
    </bean>
    
    <bean id="employeeDAO" class="cn.dusk._1_extends.EmployeeDAOImpl" 
    	parent="baseDAO"/>
    	
    <bean id="DepartmentDAO" class="cn.dusk._1_extends.DepartmentDAOImpl" 
    	parent="baseDAO"/>
    
</beans>

测试类App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	@Autowired
	private EmployeeDAOImpl e;
	@Autowired
	private DepartmentDAOImpl d;
	
	@Test
	public void test() throws Exception {
		System.out.println(e);
		System.out.println(d);
	}
}

二.注解注入

Autowired和Qualifier标签:

  1. 通过@Autowired标签可以让Spring自动的把属性需要的对象从Spring容器找出来,并注入给该属性。
  2. 第三方程序:Spring3.0之前,需要手动配置@Autowired解析注解程序,Spring就会自动的加入针对@Autowired标签的解析程序。从Spring3.0开始,可以不再需要改配置了。如果不在Spring的测试环境中,也找到@Autowired的解析代码,此时也必须配置.
<context:annotation-config/>
  1. @Autowired标签贴在字段或者setter方法上。
  2. @Autowired可以同时为一个属性注入多个对象。
public void setXxx(OtherBean1 other1,OtherBean2 other2) {}
  1. 使用@Autowired标签可以注入Spring内置的重要对象,比如BeanFactory,ApplicationContext。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class SpringTest {
    @Autowired
    private ApplicationContext ctx;
}
  1. 默认情况下@Autowired标签必须要能找到对应的对象,否则报错。不过,可使用required=false来避免该问题:@Autowired(required=false)
  2. @Autowired找bean的方式:
    1. 首先按照依赖对象的类型找,如果找到则使用setter方法或者字段直接注入;
    2. 如果在Spring上下文中找到多个匹配的类型,再按照名字去找,如果没有匹配则报错;
    3. 可以通过使用@Qualifier(“otherBean”)标签来规定依赖对象按照bean的id+类型去找;

@Resource(name="otherBean2")
private OtherBean2 other2;

等价于

@Autowired
@Qualifier("otherBean2")
private OtherBean2 other2;

@Autowired VS @Resource: 都是只能注入符合类型
1. @Autowired:是Spring定义的标签,所以不太稳定,并且对象和spring框架关联(Spring对我们的代码有侵入);
2. @Resouce:是J2EE的规范,所以稳定,在J2EE规范容器中也能正常使用;

三.使用注解简化IoC

使用标签简化IoC:

  1. 使用标签来完成IoC,就必须有IoC标签的解析器:
    使用context:component-scan来扫描spring需要管理的bean
    base-package就告诉spring,去哪些包及其子包里去扫描bean,如果有多个包需要被扫描;只需要用逗号隔开多个包即可

    <context:component-scan base-package="com.dusk.oa.dao,cn.com.dusk.service" />
    
  2. 标注Bean的注解:@Component
    默认情况,直接使用类的名字(首字母小写作为bean的名字)
    如果要修改bean的名称;直接使用value属性来重新定义bean的名称

    @Component("otherbean")
      public class OtherBean {}
    
  3. 使用@Component的限制:

    1. 不能运用到静态工厂方法和实例工厂方法,但是可以使用到FactoryBean;
    2. 对于没有源代码的类(框架内部的预定义类),只能用XML配置;
  4. bean组件版型标签
    bean组件版型:

    @Service用于标注业务层组件、
    @Controller用于标注控制层组件(如struts中的action)
    @Repository用于标注数据访问组件,即DAO组件。
    @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
    
  5. 指定bean的作用域:@Scope(“prototype”)

  6. 初始化和销毁方法

    @PostConstruct
    public void init() {
    相当于<bean init-method="init" />
    @PreDestroy
    public void destory() {
    相当于<bean destroy-method="destory" />
    
  7. 选用xml还是注解:
    1). Annotation:使用方便,XML文件很小,但是,依赖关系又重新回到了代码当中;
    2). XML:使用稍微复杂,但是,代码很干净,代码不会跟任何框架产生关系;XML安全;
    两种方式都必须掌握;(不是你写类和AOP必须使用XML配置,其他使用注解)

配置文件app-context.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: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">
        
   <!--ioc解析器:组件扫描器 -->
   <context:component-scan base-package="cn.dusk._3_ioc_anno"/>
   <!-- 自动DI解析器 -->
    <context:annotation-config/>
</beans>

OtherBean类

@Component
public class OtherBean {

}

SomeBean类

@ToString
@Component("beanSome")
public class SomeBean {
	@Resource
	private OtherBean other1;
	public SomeBean() {
		System.out.println("创建对象");
	}
	public void work() {
		System.out.println("SomeBean.work");
	}
	@PostConstruct
	public void init() {
		System.out.println("对象初始化");
	}
	@PreDestroy
	public void destroy() {
		System.out.println("对象销毁");
	}
}

App测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	@Autowired
	private SomeBean someBean;
	@Test
	public void test() throws Exception {
		someBean.work();
	}
}

四.综合案例使用注解

项目结构
image

UserAction类

@Controller
@Scope("prototype")
public class UserAction {
	@Autowired
	private IUserService service;
	public String regist() {
		service.regist(new User("zhen,ji"));
		return "success";
	}
}

IUserDAO接口

public interface IUserDAO {
	void save(User user);
}

UserDAOImpl实现类

@Repository
public class UserDAOImpl implements IUserDAO{

	public void save(User user) {
		System.out.println("保存一个用户"+user);
	}

}

实体类

@Setter@Getter@ToString
@AllArgsConstructor
public class User {
	private String name;
}

接口IUserService

public interface IUserService {
	void regist(User u);
}

实现类UserServiceImpl

@Service
public class UserServiceImpl implements IUserService{
	@Autowired
	private IUserDAO dao;
	
	public void regist(User u) {
		dao.save(u);
	}
}

测试类App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	@Autowired
	private UserAction action;
	@Test
	public void testRegist() throws Exception {
		action.regist();
	}
	
}

配置文件App-context.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: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">
	<!-- 配置自动装配解析器 -->        
	<context:annotation-config/>
	<!-- 组件扫描解析器 -->
	<context:component-scan base-package="cn.dusk._4_regist_anno"/>
</beans>

五.装饰设计模式

装饰设计模式:在不必改变源代码基础上,动态地扩展一个对象的功能。
它是通过创建一个包装对象,也就是包裹真实的对象。
说的直白点,就是对已有对象进行功能增强!


得定义一个类(Service的包装类):
目的:增强
ServiceImpl中的save和update方法.
做什么增强:
1. 在调用save方法之前:开启事务:
2. 正常调用完save方法之后:提交事务:
3. 如果调用save方法出现异常:回滚事务:

TransactionManager事务

//事务管理器,作用各种数据库的事务
public class TransactionManager {
	public void begin() {
		System.out.println("开始事务");
	}
	public void commit() {
		System.out.println("提交事务");
	}
	public void rollback() {
		System.out.println("回滚事务");
	}
	public Object allInOne(ProceedingJoinPoint point) {
		Object res = null;
		try {
			//开始事务
			begin();
			//业务方法
			res = point.proceed();
			//提交事务
			commit();
		} catch (Throwable e) {
			//回滚事务
			rollback();
		}
		return res;
	}
}

IUserService接口

public interface IUserService {
	void save();
	void update();
}

实现类UserServiceImpl

@Service
public class UserServiceImpl implements IUserService{
	
	public void save() {
		System.out.println("保存一个对象 ");
	}

	public void update() {
		System.out.println("更新 一个对象");
	}
}

UserServiceMarpper装饰类

public class UserServiceMarpper implements IUserService{
	private IUserService targer;
	private TransactionManager tm;
	
	public UserServiceMarpper(IUserService targer, TransactionManager tm) {
		this.targer = targer;
		this.tm = tm;
	}

	public void save() {
		try {
			tm.begin();
			targer.save();
			tm.commit();
		}catch(Exception e) {
			tm.rollback();
		}
	}
	
	public void update() {
		try {
			tm.begin();
			System.out.println(1/0);
			targer.update();
			tm.commit();
		}catch(Exception e) {
			tm.rollback();
		}
	}
}

配置文件App-context.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: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">
	<!-- 配置自动装配解析器 -->        
	<context:annotation-config/>
	<!-- 组件扫描解析器 -->
	<context:component-scan base-package="cn.dusk._5_aop.warpper"/>
</beans>

测试类App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	TransactionManager tm = new TransactionManager(); 
	IUserService targer = new UserServiceImpl();
	@Test
	public void testWarpper() throws Exception {
		UserServiceMarpper usm = new UserServiceMarpper(targer, tm); 
		usm.save();
		usm.update();
	}
}

六.静态代理

  1. 静态代理(proxy):在程序运行前就已经存在代理类的字节码文件,代理对象和真实对象的关系在程序运行前就确定了。

  2. 优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。

  3. 缺点:

    1. 代理对象的某个接口只服务于某一种类型的对象,也就是说每一个真实对象都得创建一个代理对象。
    2. 如果需要代理的方法很多,则要为每一种方法都进行代理处理。
    3. 如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。

UserServiceProxy代理类

@Component
public class UserServiceProxy implements IUserService{
	@Setter
	private IUserService us;
	@Setter
	private TransactionManager tm;
	public void save() {
		try {
			tm.begin();
			us.save();
			tm.commit();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void update() {
		try {
			tm.begin();
			us.update();
			System.out.println(1/0);
			tm.commit();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

app-cntext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
 	   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/context
        http://www.springframework.org/schema/context/spring-context.xsd">
	<!-- 配置自动装配解析器 -->        
	<context:annotation-config/>
	<!-- 组件扫描解析器 -->
	<context:component-scan base-package="cn.dusk._5_aop.static_proxy"/>
	<!-- 配置事务管理器 -->
	<bean id="transactionManager" class="cn.dusk._5_aop.TransactionManager"/>
	
	<bean id="userServiceProxy" class="cn.dusk._5_aop.static_proxy.UserServiceProxy">
		<property name="tm" ref="transactionManager"/>
		<property name="us">
			<bean class="cn.dusk._5_aop.warpper.service.impl.UserServiceImpl"/>
		</property>
	</bean>
</beans>

App测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	@Autowired
	private UserServiceProxy proxy;
	@Test
	public void testSave() throws Exception {
		proxy.save();
	}
	
	@Test
	public void testUpdate() throws Exception {
		proxy.update();
	}
}

七.JDK动态代理和CGLIB动态代理

动态代理类是在程序运行期间由JVM通过反射等机制动态的生成的,所以不存在代理类的字节码文件。代理对象和真实对象的关系是在程序运行事情才确定的。

JDK动态代理API分析:(只能对接口进行代理)

  1. java.lang.reflect.Proxy 类:
    Java 动态代理机制生成的所有动态代理类的父类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
主要方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler hanlder)
方法职责:为指定类加载器、一组接口及调用处理器生成动态代理类实例 
参数:
   loader		:类加载器
   interfaces	:模拟的接口
   hanlder		:代理执行处理器
返回:动态生成的代理对象
  1. java.lang.reflect.InvocationHandler接口:
public Object invoke(Object proxy, Method method, Object[] args)
方法职责:负责集中处理动态代理类上的所有方法调用
参数: 
    proxy      :生成的代理对象
    method	   :当前调用的真实方法对象
    args       :当前调用方法的实参
返回: 真实方法的返回结果
  1. jdk动态代理操作步骤
    1.实现InvocationHandler接口,创建自己增强代码的处理器。
    2. 给Proxy类提供ClassLoader对象和代理接口类型数组,创建动态代理对象。
    3. 在处理器中实现增强操作。

JdkProxyhandler代理类

@SuppressWarnings("all")
@Component
public class JdkProxyhandler implements InvocationHandler{
	@Setter
	private Object target;//目标对象
	@Setter
	private TransactionManager txManager;//事务管理
	//获取代理对象
	public <T>T getInstance(){
		return (T)Proxy.newProxyInstance(
				JdkProxyhandler.class.getClassLoader(),//类加载器
				target.getClass().getInterfaces(),//对哪些接口做代理
				this);//方法处理,(如何增强)
	}
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object res = null;
		try {
			txManager.begin();//开始事务
			res = method.invoke(target, args);//业务操作
			System.out.println(1/0);
			txManager.commit();//提交事务
		} catch (Exception e) {
			txManager.rollback();
			e.printStackTrace();
		}
		return res;
	}

}


CGLIB动态代理:

原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。

CglibCallback代理类

@SuppressWarnings("all")
//InvocationHandler有两个需要的是Spring里面的那个
public class CglibCallback implements InvocationHandler{
	@Setter
	private Object target;//真实类型
	@Setter
	private TransactionManager txManager;//事务管理器
	
	//创建代理对象
	public <T>T getInstance(){
		Enhancer en = new Enhancer();
		en.setSuperclass(UserServiceImpl.class);
		en.setCallback(this);
		return (T)en.create();
	}
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object res = null;
		try {
			txManager.begin();//开始事务
			res = method.invoke(target, args);//业务操作
			System.out.println(1/0);
			txManager.commit();//提交事务
		} catch (Exception e) {
			e.printStackTrace();//回滚事务
			txManager.rollback();
		}
		return res;
	}

}

app-context.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: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">
	<!-- 配置自动装配解析器 -->        
	<context:annotation-config/>
	<!-- 组件扫描解析器 -->
	<context:component-scan base-package="cn.dusk._5_aop.warpper"/>
	<!-- 配置动态代理处理器 -->
	<bean id="transactionManager" class="cn.dusk._5_aop.TransactionManager"/>
	<bean id="jdkProxyhandler" class="cn.dusk._5_aop.dy_proxy.JdkProxyhandler">
		<property name="target">
			<bean class="cn.dusk._5_aop.warpper.service.impl.UserServiceImpl"/>
		</property>
		<property name="txManager" ref="transactionManager"/>
	</bean>
	
	<bean id="cglibCallback" class="cn.dusk._5_aop.dy_proxy.CglibCallback">
		<property name="txManager" ref="transactionManager"/>
		<property name="target">
			<bean class="cn.dusk._5_aop.warpper.service.impl.UserServiceImpl"/>
		</property>
	</bean>
</beans>

测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	@Autowired
	private JdkProxyhandler hander;
	@Autowired
	private CglibCallback callback;
	
	@Test
	public void teestCglibSave() throws Exception {
		//获取动态代理对象
		UserServiceImpl proxy = callback.getInstance();
		System.out.println("真实类型" + proxy.getClass());
		proxy.save();
	}
	
	@Test
	public void testCglibUpdate() throws Exception {
		//获取动态代理对象
		UserServiceImpl proxy = callback.getInstance();
		proxy.update();
	}
	
	@Test
	public void testSave() throws Exception {
		//获取到动态代理对象
		IUserService proxy = hander.getInstance();
		//
		System.out.println(proxy.getClass());
		proxy.save();
	}
	
	@Test
	public void testUpdate() throws Exception {
		IUserService proxy = hander.getInstance();
		proxy.update();
	}
}

八.AOP概念

  1. AOP的目的:
    AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任(例如事务处理、日志管理、权限控制等)封装起来,
    便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性。
    说人话:把业务方法中与业务无关的操作抽离到不同的对象的方法中,最后使用动态代理的方式组合起来

  2. AOP的优势:
    降低模块的耦合度、使系统容易扩展、更好的代码复用性.
    Spring的AOP使用动态代理实现:
    如果一个类实现了接口,那么spring就使用JDK的动态代理完成AOP;
    如果一个类没有实现接口,那么spring就是用cglib完成AOP;

  3. AOP当中的概念:

    1. 切入点(Pointcut):在哪些类,哪些方法上切入(where);
    2. 增强(Advice): 早期翻译为通知,在方法执行的什么时机(when:方法前/方法后/方法前后)做什么(what:增强的功能);
    3. 切面(Aspect): 切面=切入点+增强,通俗点就是:在什么时机,什么地点,做什么增强!
    4. 织入(Weaving): 把切面加入到对象,并创建出代理对象的过程。(该过程由Spring来完成)。

九.AOP的XML配置

AOP的规范本应该由SUN公司提出,但是被AOP联盟捷足先登.AOP联盟制定AOP规范
首先就要解决一个问题,怎么表示在哪些方法上增强—— AspectJ(语言)。
AspectJ切入点语法如下(表示在哪些包下的哪些类的哪些方法上做切入):

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

翻译成中文:
execution(<修饰符>? <返回类型> <声明类型>? <方法名>(<参数>) <异常>?)

Class类中的forName方法的完整签名:

public static java.lang.Class java.lang.Class.forName(String className) throws ClassNotFoundException

在所有的业务层方法上做增强:
execution(* com.dusk.pss.service.Service.(…))


Spring配置AOP的准备工作

  1. 引入Spring AOP开发依赖的jar包:
    spring-aop-4.2.4.RELEASE.jar
    aopalliance-1.0.0.jar
    aspectjweaver-1.8.7.jar
  2. 配置aop名称空间:
<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: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/aop<!--这里-->
        http://www.springframework.org/schema/aop/spring-aop.xsd"><!--这里-->
<aop:config>
	where:在哪做增强
	<aop:pointcut expression="execution(* cn.dusk._6_aop.service.*Service.*(..))" id="pc"/>
	what:做怎么增强
	<aop:aspect ref="txManager">
		when:在什么时机做增强
		aop:before:在目标方法调用前做增强
		<aop:before method="begin" pointcut-ref="pc"/>
		aop:after-returning:方法正常结束时做后置增强
		<aop:after method="commit" pointcut-ref="pc"/>
		aop:after-throwing:方式异常结束时做后置增强
		<aop:after-throwing method="rollback" pointcut-ref="pc"/>
	</aop:aspect>
</aop:config>

十.Spring中的各种增强

各种不同的增强:
aop:before(前置增强):在方法执行之前执行增强;
aop:after-returning(后置增强):在方法正常执行完成之后执行增强(中间没有遇到任何异常);
aop:after-throwing(异常增强):在方法抛出异常退出时执行增强代码;
aop:after(最终增强):在方法执行之后执行,相当于在finally里面执行;可以通过配置throwing来获得拦截到的异常信息
aop:around(环绕增强):最强大的一种增强类型。 环绕增强可以在方法调用前后完成自定义的行为,环绕通知有两个要求,
                      1,方法必须要返回一个Object(返回的结果)
                      2,方法的第一个参数必须是ProceedingJoinPoint(可以继续向下传递的切入点)

接口IUserService

public interface IUserService {
	void save();
	void update();
}

UserServiceImpl实现类

@Service
public class UserServiceImpl implements IUserService{
	
	public void save() {
		System.out.println("保存一个对象 ");
	}

	public void update() {
		System.out.println(1/0);
		System.out.println("更新 一个对象");
	}
}

配置App-context.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: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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!-- 配置自动装配解析器 -->        
	<context:annotation-config/>
	<!-- 组件扫描解析器 -->
	<context:component-scan base-package="cn.dusk._6_aop"/>
	<!-- 配置事务管理器 -->
	<bean id="txManager" class="cn.dusk._5_solvt.TransactionManager"/>
	<bean id="userServiceImpl" class="cn.dusk._6_aop.service.impl.UserServiceImpl"></bean>
	
	<aop:config>
		<!-- 在哪里做增强 -->
		<aop:pointcut expression="execution(* cn.dusk._6_aop.service.*Service.*(..)))" id="all"/>
		<!-- 做什么增强 -->
		<aop:aspect ref="txManager">
			<!-- 在什么时机做增强 -->
			<!-- aop:around:环绕增强 -->
			<aop:around method="allInOne" pointcut-ref="all"/>
		</aop:aspect>
	</aop:config>
    <!-- AOP配置:3w what/where/when
	<aop:config>
		where:在哪做增强
		<aop:pointcut expression="execution(* cn.dusk._6_aop.service.*Service.*(..))" id="pc"/>
		what:做怎么增强
		<aop:aspect ref="txManager">
			when:在什么时机做增强
			aop:before:在目标方法调用前做增强
			<aop:before method="begin" pointcut-ref="pc"/>
			aop:after-returning:方法正常结束时做后置增强
			<aop:after method="commit" pointcut-ref="pc"/>
			aop:after-throwing:方式异常结束时做后置增强
			<aop:after-throwing method="rollback" pointcut-ref="pc"/>
		</aop:aspect>
	</aop:config> -->
</beans>

测试类App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	@Autowired
	private IUserService us;
	@Test
	public void testSave() throws Exception {
		us.save();
	}
	
	@Test
	public void testUpdate() throws Exception {
		us.update();
	}
}

十一.使用注解配置AOP

接口

public interface IUserService {
	void save();
	void update();
}

实现类

@Service
public class UserServiceImpl implements IUserService{
	
	public void save() {
		System.out.println("保存一个对象 ");
	}

	public void update() {
		System.out.println(1/0);
		System.out.println("更新 一个对象");
	}
}

TransactionManager事务管理器

//事务管理器,作用各种数据库的事务
@Component
@Aspect
public class TransactionManager {
	@Pointcut("execution(* cn.dusk._7_annotaion.service.*Service.*(..))")
	public void pc() {}
	
	public void begin() {
		System.out.println("开始事务");
	}
	public void commit() {
		System.out.println("提交事务");
	}
	public void rollback() {
		System.out.println("回滚事务");
	}
	
	@Around("pc()")
	public Object allInOne(ProceedingJoinPoint point) {
		Object res = null;
		try {
			//开始事务
			begin();
			//业务方法
			res = point.proceed();
			System.err.println(1/0);
			//提交事务
			commit();
		} catch (Throwable e) {
			//回滚事务
			rollback();
		}
		return res;
	}
}

配置信息App-context.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: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/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
	<!-- 配置自动装配解析器 -->        
	<context:annotation-config/>
	<!-- 组件扫描解析器 -->
	<context:component-scan base-package="cn.dusk._7_annotaion"/>
	<!-- 自动DI解析器 -->	
	<context:annotation-config/>
	<!-- 自动代理 -->
	<aop:aspectj-autoproxy/>
</beans>

测试类App

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class App {
	@Autowired
	private IUserService us;
	@Test
	public void testSave() throws Exception {
		us.save();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值