Spring的第二节(注解模式实现Spring、代理模式(静态代理、动态代理、cglib代理))、AOP编程

一:注解模式实现Spring

@Component:这个注解的作用就是将当前的类生成对象并且放入到IOC容器中(这个用在类上面)
@Autowired :这个注解相当于是通过类型来进行注入(用在依赖对象的注入上面:按照类型来进行注入)
@Resource:表示的是从IOC容器里面去找名字一致的进行赋值(用在依赖对象的注入上面)
@Service :这个注解的作用就是将当前的类生成对象并且放入到IOC容器中  这个主不过带有语义化而已  这个经常用在业务逻辑层(用在业务逻辑层类上面)
@Repository :这个注解的作用就是将当前的类生成对象并且放入到IOC容器中  这个主不过带有语义化而已  这个经常用在DAO层(用在DAO层类上面)
@PostConstruct:这个注解的作用就是可以在对象放入IOC容器之前做一些初始化操作(用在业务逻辑层的初始化方法上面)
@PreDestroy:这个注解的作用就是在对象销毁之前倍调用(用在业务逻辑层的销毁的方法上面)
@Scope(value="singleton")  //表示的是设置是单例的还是多例的(用在类上面)

二:代理的设计模式

       什么是设计模式:就是按照JAVA前辈们总结的一定的步骤来完成相应的功能的这种写代码的模式就叫做设计模式

       代理的设计模式也是23中设计模式之一

       代理的设计模式能够解决的问题:是监听一个类里面方法的执行、或者在方法的执行前后动态的植入代码

  1>:静态代理

          静态代理的前提:被代理的类必须要实现接口、否则被代理的类没有办法完成静态代理

          1>:编写被代理类实现的接口

public interface IUserDAO {
    /**
     * 保存用户
     * @Title: save 
     * @Description: TODO
     * @param @param user    
     * @return void    
     * @throws
     */
	public void save(User user);
	/**
	 * 更新用户数据
	 * @Title: update 
	 * @Description: TODO
	 * @param     
	 * @return void    
	 * @throws
	 */
	public void update(); 
	
}

        2>:编写被代理的类

public class UserDAO implements IUserDAO{

	@Override
	public void save(User user) {
		System.out.println("保存数据中....");
	}
	@Override
	public void update() {
		System.out.println("更新数据中....");
	}
}

      3>:编写代理的类

public class UserDAOProxy implements IUserDAO{
	private UserDAO userDAO=null;
	public UserDAOProxy(UserDAO userDAO) {
		this.userDAO=userDAO;
	}
	@Override
	public void save(User user) {
		//检测到了 userDAO的执行
		System.out.println("打开事务...");
		userDAO.save(user);
		System.out.println("关闭事务...");
	}
	@Override
	public void update() {
		userDAO.update();
	}

}

     4>:测试代理类的功能

	@Test
	public void testStaticProxy() throws Exception {
		UserDAOProxy proxy=new UserDAOProxy(new UserDAO());
		proxy.save(new User(1,"小波波"));
	}
	

   2>:动态代理(JDK代理)

       动态代理的前提:被代理的类必须要实现接口、动态代理的原理实际上是生成了被代理类接口的实现类,在需要代理的地方通过多态的模式传入了实际的代理类的对象、其原理有点类似于静态代理、只不过生成代理类的这个实现是JDK提供的API来实现的

      1>:编写被代理类的接口:和上面一样

      2>:编写被代理的类:和上面一样

      3>:编写代理的实现

     

@Test
	public void testDynamic() throws Exception {	
		final UserDAO userDAO=new UserDAO();
		/**
		 * 
		 * 
		 * classloader:这个参数不用记   就是当前的这个类.class.getClassLoader
		 * interfaces:这个分成两种情况(实现的接口)
		 *        1>:本身是类但是实现了接口  类.class.getInterface()
		 *        2>:本身是一个接口     new Class[]{接口.class}
		 * invocationHandele:这个参数就是用来拦截方法的执行的  也就是说每一个方法的执行都会经过实现了这个接口的方法       
		 *     
		 */
		IUserDAO userDAO2=(IUserDAO) Proxy.newProxyInstance(UserDAO.class.getClassLoader(),
				UserDAO.class.getInterfaces(),
				new InvocationHandler() {
					
			        //这个方法表示 只要被代理的这个类里面方法要执行  都要进过下面的这个回调的方法
					/**
					 * proxy:表示生成的这个代理类的对象
					 * method:表示的是这个即将要执行的这个方法
					 * args:这个表示的是 执行方法所需要的参数
					 * 
					 * 返回值表示的是执行完这个方法之后的返回值
					 * 
					 */
			        @Override
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
			        	System.out.println("我是小波波");
						//这里执行原来被代理类的这个方法
			        	Object object=method.invoke(userDAO, args);
			        	System.out.println("我是小波波");
						return object;
					}
				});
		userDAO2.save(null);
	}

  3>:cglib代理

     鉴于动态代理和静态代理被代理的类都必须要实现接口、对于一个单纯的没有实现接口的类而言生成代理对象就不好使了、所以在这种条件下我们的cglib代理就应运而生了

     cglib代理的实质是:生成了被代理类的子类对象、通过了子类去访问父类的方法、这里实际上使用的是多态的玩法

     1>:导入cglib代理的相关包

     2>:编写被代理类的对象

public class UserDAO{

	public void save(User user) {
		System.out.println("保存数据中....");
	}
	public void update() {
		System.out.println("更新数据中....");
	}
}

     3>:编写代理类

public class UserDAOProxy implements MethodInterceptor{
	
	private UserDAO userDAO=null;
	
	public UserDAOProxy(UserDAO userDAO) {
		this.userDAO=userDAO;
	}

	//第一步:在这个类里面编写一个方法返回被代理类的子类对象
	
	public UserDAO getUserDAOProxy(){
		
		//第一步:生成Enhancer对象
		Enhancer enhancer=new Enhancer();
		//设置生成的代理类的父类
		enhancer.setSuperclass(userDAO.getClass());
		//设置方法的回调
		enhancer.setCallback(this);
		//生成代理类
		return (UserDAO) enhancer.create();
	}

    /**
     * 这个就是那个检测类中方法执行的那个方法
     */
	@Override
	public Object intercept(Object proxy, Method method, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		//获取请求的方法
		String reqName=method.getName();
		if("save".equals(reqName)){
			System.out.println("打开事务....");
			Object result= method.invoke(userDAO, arg2);
			System.out.println("关闭事务....");
			return result;
		}else{
			return method.invoke(userDAO, arg2);
		}
	}
}

      4>:测试代码如下

@Test
	public void testCglib() throws Exception {
		UserDAO userDAO=new UserDAOProxy(new UserDAO()).getUserDAOProxy();
		userDAO.update();
	}


三:AOP编程

什么是AOP编程

         AOP编程是面向切面的编程

          什么叫面向切面的编程呢?

          简单的跟你说:就是在开发中将重复的代码抽取出来  形成一个类 这个类就叫做切面类

          在我们的代码执行的时候  通过代理的设计模式  动态的植入在我们需要这个代码的地方植入我们所需要的代码的这种编程思想  就叫做 面向切面的编程

          切面类:就是抽取出来的公共代码形成的一个类  这个类就叫做切面类

          切入点:就是我们所需要代码的这个地方

          切入点表达式:使用表达式来形容我们代码所需要的这个地点的这个表达式  就叫做切入点表达式 

1>:首写AOP实现编程  

         需求:在DAO执行的前后动态的植入我们的事务代码

          1>:编写DAO的接口
public interface IUserDAO {
	public void save();
	public void update();
}
           2>:编写DAO接口的实现
public class UserDAO implements IUserDAO{
	
	public void save(){
		System.out.println("正在保存数据...");
	}
	
	public void update(){
		System.out.println("正在更新数据....");
	}
}
          3>:编写AOP切面类
@Component
public class Aop {

	public void startTranaction(){
		System.out.println("打开事务...");
	}
	
	public void closeTranaction(){
		System.out.println("关闭事务...");
	}	
	
}
         4>:编写业务逻辑类
@Service
public class UserService {

	@Autowired
	private UserDAO userDAO=null;
	
	public void register(){
		userDAO.save();
	}
	
	public void update(){
		userDAO.update();
	}
}
         5>:编写代理类
/**
 * 使用Cglib代理
 * @ClassName: UserDAOProxy 
 * @Description: TODO
 * @author 小波波
 * @date 2018-3-27 下午3:16:02 
 *
 */
public class UserDAOProxy implements MethodInterceptor{
    
	private UserDAO userDAO=new UserDAO();
	
	@Autowired
	private Aop aop=null;
	
	public UserDAO getUserDAOProxy(){
		Enhancer enhancer=new Enhancer();
		enhancer.setSuperclass(UserDAO.class);
		enhancer.setCallback(this);
		return (UserDAO) enhancer.create();
	}
	@Override
	public Object intercept(Object arg0, Method method, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		
		System.out.println("当前执行的方法是:"+method.getName());
		//这里是不是就应该
		aop.startTranaction();
		Object result=method.invoke(userDAO, arg2);
		aop.closeTranaction();
		return result;
	}
}
           6>:编写测试类
@Test
	public void testAop() throws Exception {
		//获取IOC的容器
		ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("config/bean-aop.xml");
	    //可能就是获取对象了
		UserService userService=applicationContext.getBean(UserService.class);
	    userService.register();
	    System.out.println("---------------");
	    userService.update();
	}
           7>:附带配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    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">
    <!--申明工厂的bean-->
    <bean id="userDAOProxy" class="com.qf.aop1.UserDAOProxy"></bean>
    <!--神经我们的方法生成的bean-->
    <bean factory-bean="userDAOProxy" factory-method="getUserDAOProxy"></bean>
    
   <!--配置一个扫描器来完成对刚才注解的扫描工作-->
    <context:component-scan base-package="com.qf.aop1"></context:component-scan>
        
</beans>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值